@samitouri / QOS-React-2 / commits / 01fb68b9bf

Don't ignore dependencies for render phase update (#16574)

Dan Abramov committed Aug 28, 2019 at 16:55 UTC 01fb68b9bf680ab8bbf96e86501e0fc540b3cc97
2 files changed +48
packages/react-reconciler/src/ReactFiberHooks.js
+5
@@ -428,6 +428,11 @@ export function renderWithHooks(
428 do {
429 didScheduleRenderPhaseUpdate = false;
430 numberOfReRenders += 1;
431 + if (__DEV__) {
432 + // Even when hot reloading, allow dependencies to stabilize
433 + // after first render to prevent infinite render phase updates.
434 + ignorePreviousDependencies = false;
435 + }
436
437 // Start over from the beginning of the list
438 nextCurrentHook = current !== null ? current.memoizedState : null;
packages/react-refresh/src/__tests__/ReactFresh-test.js
+43
@@ -2350,6 +2350,49 @@ describe('ReactFresh', () => {
2350 }
2351 });
2352
2353 + // This pattern is inspired by useSubscription and similar mechanisms.
2354 + it('does not get into infinite loops during render phase updates', () => {
2355 + if (__DEV__) {
2356 + render(() => {
2357 + function Hello() {
2358 + const source = React.useMemo(() => ({value: 10}), []);
2359 + const [state, setState] = React.useState({value: null});
2360 + if (state !== source) {
2361 + setState(source);
2362 + }
2363 + return <p style={{color: 'blue'}}>{state.value}</p>;
2364 + }
2365 + $RefreshReg$(Hello, 'Hello');
2366 + return Hello;
2367 + });
2368 +
2369 + const el = container.firstChild;
2370 + expect(el.textContent).toBe('10');
2371 + expect(el.style.color).toBe('blue');
2372 +
2373 + // Perform a hot update.
2374 + act(() => {
2375 + patch(() => {
2376 + function Hello() {
2377 + const source = React.useMemo(() => ({value: 20}), []);
2378 + const [state, setState] = React.useState({value: null});
2379 + if (state !== source) {
2380 + // This should perform a single render-phase update.
2381 + setState(source);
2382 + }
2383 + return <p style={{color: 'red'}}>{state.value}</p>;
2384 + }
2385 + $RefreshReg$(Hello, 'Hello');
2386 + return Hello;
2387 + });
2388 + });
2389 +
2390 + expect(container.firstChild).toBe(el);
2391 + expect(el.textContent).toBe('20');
2392 + expect(el.style.color).toBe('red');
2393 + }
2394 + });
2395 +
2396 it('can hot reload offscreen components', () => {
2397 if (__DEV__) {
2398 const AppV1 = prepare(() => {