Files
react-native/packages/virtualized-lists/Lists/StateSafePureComponent.js
T
Nick Gerleman 0daf83ac51 Reconnect VirtualizedList Source History 2/2 (Apply D41745930 + history, D42805202, D43063551)
Summary:
This change re-applies D41745930 (https://github.com/facebook/react-native/commit/2e3dbe9c2fbff52448e2d5a7c1e4c96b1016cf25) (and D42805202 (https://github.com/facebook/react-native/commit/1479b2ac26fded3840c596f53e6eb86a4b0c2c71) which was also partially reverted), re-registers additions as moves, then applies D43063551 which has been added to the changes since migration.

Changelog: [Internal]

Reviewed By: hoxyq

Differential Revision: D43068114

fbshipit-source-id: 72997700bf9962d82a988599481e255b69e68a9b
2023-02-06 20:00:19 -08:00

86 lines
2.1 KiB
JavaScript

/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
import invariant from 'invariant';
import * as React from 'react';
/**
* `setState` is called asynchronously, and should not rely on the value of
* `this.props` or `this.state`:
* https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous
*
* SafePureComponent adds runtime enforcement, to catch cases where these
* variables are read in a state updater function, instead of the ones passed
* in.
*/
export default class StateSafePureComponent<
Props,
State: interface {},
> extends React.PureComponent<Props, State> {
_inAsyncStateUpdate = false;
constructor(props: Props) {
super(props);
this._installSetStateHooks();
}
setState(
partialState: ?($Shape<State> | ((State, Props) => ?$Shape<State>)),
callback?: () => mixed,
): void {
if (typeof partialState === 'function') {
super.setState((state, props) => {
this._inAsyncStateUpdate = true;
let ret;
try {
ret = partialState(state, props);
} catch (err) {
throw err;
} finally {
this._inAsyncStateUpdate = false;
}
return ret;
}, callback);
} else {
super.setState(partialState, callback);
}
}
_installSetStateHooks() {
const that = this;
let {props, state} = this;
Object.defineProperty(this, 'props', {
get() {
invariant(
!that._inAsyncStateUpdate,
'"this.props" should not be accessed during state updates',
);
return props;
},
set(newProps: Props) {
props = newProps;
},
});
Object.defineProperty(this, 'state', {
get() {
invariant(
!that._inAsyncStateUpdate,
'"this.state" should not be acceessed during state updates',
);
return state;
},
set(newState: State) {
state = newState;
},
});
}
}