@samitouri / QOS-React-1 / commits / 17ca4b157f

Fix useResourceEffect in Fizz (#31758)

We're seeing errors when testing useResourceEffect in SSR and it turns out we're missing the noop dispatcher function on Fizz. I tested a local build with this change and it resolved the late mutation errors in the e2e tests.

Jack Pope committed Dec 13, 2024 at 11:26 UTC 17ca4b157fcba6c734583513353ba72376a7ba2d
2 files changed +54
packages/react-dom/src/__tests__/ReactDOMServerIntegrationHooks-test.js
+48
@@ -27,6 +27,7 @@ let useRef;
27 let useImperativeHandle;
28 let useInsertionEffect;
29 let useLayoutEffect;
30 +let useResourceEffect;
31 let useDebugValue;
32 let forwardRef;
33 let yieldedValues;
@@ -51,6 +52,7 @@ function initModules() {
52 useImperativeHandle = React.useImperativeHandle;
53 useInsertionEffect = React.useInsertionEffect;
54 useLayoutEffect = React.useLayoutEffect;
55 + useResourceEffect = React.experimental_useResourceEffect;
56 forwardRef = React.forwardRef;
57
58 yieldedValues = [];
@@ -653,6 +655,52 @@ describe('ReactDOMServerHooks', () => {
655 });
656 });
657
658 + describe('useResourceEffect', () => {
659 + gate(flags => {
660 + if (flags.enableUseResourceEffectHook) {
661 + const yields = [];
662 + itRenders(
663 + 'should ignore resource effects on the server',
664 + async render => {
665 + function Counter(props) {
666 + useResourceEffect(
667 + () => {
668 + yieldValue('created on client');
669 + return {resource_counter: props.count};
670 + },
671 + [props.count],
672 + resource => {
673 + resource.resource_counter = props.count;
674 + yieldValue('updated on client');
675 + },
676 + [props.count],
677 + () => {
678 + yieldValue('cleanup on client');
679 + },
680 + );
681 + return <Text text={'Count: ' + props.count} />;
682 + }
683 +
684 + const domNode = await render(<Counter count={0} />);
685 + yields.push(clearLog());
686 + expect(domNode.tagName).toEqual('SPAN');
687 + expect(domNode.textContent).toEqual('Count: 0');
688 + },
689 + );
690 +
691 + it('verifies yields in order', () => {
692 + expect(yields).toEqual([
693 + ['Count: 0'], // server render
694 + ['Count: 0'], // server stream
695 + ['Count: 0', 'created on client'], // clean render
696 + ['Count: 0', 'created on client'], // hydrated render
697 + // nothing yielded for bad markup
698 + ]);
699 + });
700 + }
701 + });
702 + });
703 +
704 describe('useContext', () => {
705 itThrowsWhenRendering(
706 'if used inside a class component',
packages/react-server/src/ReactFizzHooks.js
+6
@@ -43,6 +43,7 @@ import {
43 enableUseEffectEventHook,
44 enableUseMemoCacheHook,
45 enableAsyncActions,
46 + enableUseResourceEffectHook,
47 } from 'shared/ReactFeatureFlags';
48 import is from 'shared/objectIs';
49 import {
@@ -870,6 +871,11 @@ if (enableAsyncActions) {
871 HooksDispatcher.useFormState = useActionState;
872 HooksDispatcher.useActionState = useActionState;
873 }
874 +if (enableUseResourceEffectHook) {
875 + HooksDispatcher.useResourceEffect = supportsClientAPIs
876 + ? noop
877 + : clientHookNotSupported;
878 +}
879
880 export let currentResumableState: null | ResumableState = (null: any);
881 export function setCurrentResumableState(