Skip to content

Commit f178758

Browse files
committed
Add test combining state bailout and props bailout (memo)
1 parent e7a99f9 commit f178758

File tree

1 file changed

+66
-0
lines changed

1 file changed

+66
-0
lines changed

packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js

+66
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,72 @@ describe('ReactHooks', () => {
117117
expect(root).toFlushAndYield(['Parent: 1, 2']);
118118
});
119119

120+
it('bails out in render phase if all the state is the same and props bail out with memo', () => {
121+
const {useState, memo} = React;
122+
123+
function Child({text}) {
124+
ReactTestRenderer.unstable_yield('Child: ' + text);
125+
return text;
126+
}
127+
128+
let setCounter1;
129+
let setCounter2;
130+
function Parent({theme}) {
131+
const [counter1, _setCounter1] = useState(0);
132+
setCounter1 = _setCounter1;
133+
const [counter2, _setCounter2] = useState(0);
134+
setCounter2 = _setCounter2;
135+
136+
const text = `${counter1}, ${counter2} (${theme})`;
137+
ReactTestRenderer.unstable_yield(`Parent: ${text}`);
138+
return <Child text={text} />;
139+
}
140+
141+
Parent = memo(Parent);
142+
143+
const root = ReactTestRenderer.create(null, {unstable_isConcurrent: true});
144+
root.update(<Parent theme="light" />);
145+
expect(root).toFlushAndYield([
146+
'Parent: 0, 0 (light)',
147+
'Child: 0, 0 (light)',
148+
]);
149+
expect(root).toMatchRenderedOutput('0, 0 (light)');
150+
151+
// Normal update
152+
setCounter1(1);
153+
setCounter2(1);
154+
expect(root).toFlushAndYield([
155+
'Parent: 1, 1 (light)',
156+
'Child: 1, 1 (light)',
157+
]);
158+
159+
// Update that bails out.
160+
setCounter1(1);
161+
expect(root).toFlushAndYield(['Parent: 1, 1 (light)']);
162+
163+
// This time, one of the state updates but the other one doesn't. So we
164+
// can't bail out.
165+
setCounter1(1);
166+
setCounter2(2);
167+
expect(root).toFlushAndYield([
168+
'Parent: 1, 2 (light)',
169+
'Child: 1, 2 (light)',
170+
]);
171+
172+
// Updates bail out, but component still renders because props
173+
// have changed
174+
setCounter1(1);
175+
setCounter2(2);
176+
root.update(<Parent theme="dark" />);
177+
expect(root).toFlushAndYield(['Parent: 1, 2 (dark)', 'Child: 1, 2 (dark)']);
178+
179+
// Both props and state bail out
180+
setCounter1(1);
181+
setCounter2(2);
182+
root.update(<Parent theme="dark" />);
183+
expect(root).toFlushAndYield(['Parent: 1, 2 (dark)']);
184+
});
185+
120186
it('never bails out if context has changed', () => {
121187
const {useState, useLayoutEffect, useContext} = React;
122188

0 commit comments

Comments
 (0)