mirror of
https://github.com/hanzoai/react.git
synced 2026-09-24 17:02:27 +00:00
Ensure useState and useReducer initializer functions are double invoked in StrictMode (#28248)
This commit is contained in:
committed by
GitHub
parent
560b0ddf01
commit
82e47e83ca
+13
-1
@@ -1154,6 +1154,11 @@ function mountReducer<S, I, A>(
|
||||
let initialState;
|
||||
if (init !== undefined) {
|
||||
initialState = init(initialArg);
|
||||
if (shouldDoubleInvokeUserFnsInHooksDEV) {
|
||||
setIsStrictModeForDevtools(true);
|
||||
init(initialArg);
|
||||
setIsStrictModeForDevtools(false);
|
||||
}
|
||||
} else {
|
||||
initialState = ((initialArg: any): S);
|
||||
}
|
||||
@@ -1745,8 +1750,15 @@ function forceStoreRerender(fiber: Fiber) {
|
||||
function mountStateImpl<S>(initialState: (() => S) | S): Hook {
|
||||
const hook = mountWorkInProgressHook();
|
||||
if (typeof initialState === 'function') {
|
||||
const initialStateInitializer = initialState;
|
||||
// $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
|
||||
initialState = initialState();
|
||||
initialState = initialStateInitializer();
|
||||
if (shouldDoubleInvokeUserFnsInHooksDEV) {
|
||||
setIsStrictModeForDevtools(true);
|
||||
// $FlowFixMe[incompatible-use]: Flow doesn't like mixed types
|
||||
initialStateInitializer();
|
||||
setIsStrictModeForDevtools(false);
|
||||
}
|
||||
}
|
||||
hook.memoizedState = hook.baseState = initialState;
|
||||
const queue: UpdateQueue<S, BasicStateAction<S>> = {
|
||||
|
||||
@@ -202,6 +202,46 @@ describe('ReactStrictMode', () => {
|
||||
expect(instance.state.count).toBe(2);
|
||||
});
|
||||
|
||||
// @gate debugRenderPhaseSideEffectsForStrictMode
|
||||
it('double invokes useState and useReducer initializers functions', async () => {
|
||||
const log = [];
|
||||
|
||||
function App() {
|
||||
React.useState(() => {
|
||||
log.push('Compute initial state count: 1');
|
||||
return 1;
|
||||
});
|
||||
React.useReducer(
|
||||
s => s,
|
||||
2,
|
||||
s => {
|
||||
log.push('Compute initial reducer count: 2');
|
||||
return s;
|
||||
},
|
||||
);
|
||||
|
||||
return 3;
|
||||
}
|
||||
|
||||
const container = document.createElement('div');
|
||||
const root = ReactDOMClient.createRoot(container);
|
||||
await act(() => {
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
);
|
||||
});
|
||||
expect(container.textContent).toBe('3');
|
||||
|
||||
expect(log).toEqual([
|
||||
'Compute initial state count: 1',
|
||||
'Compute initial state count: 1',
|
||||
'Compute initial reducer count: 2',
|
||||
'Compute initial reducer count: 2',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should invoke only precommit lifecycle methods twice in DEV legacy roots', async () => {
|
||||
const {StrictMode} = React;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user