Skip to content

Commit

Permalink
fix: Expose hooks through compat's ReactCurrentDispatcher (#4342)
Browse files Browse the repository at this point in the history
* fix: Re-export hooks through compat's `ReactCurrentDispatcher`

* test: Add simple test for using hooks off of `ReactCurrentDispatcher`
  • Loading branch information
rschristian committed Apr 19, 2024
1 parent 962594b commit 3123e7f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
41 changes: 37 additions & 4 deletions compat/src/render.js
Expand Up @@ -5,6 +5,25 @@ import {
toChildArray,
Component
} from 'preact';
import {
useCallback,
useContext,
useDebugValue,
useEffect,
useId,
useImperativeHandle,
useLayoutEffect,
useMemo,
useReducer,
useRef,
useState
} from 'preact/hooks';
import {
useDeferredValue,
useInsertionEffect,
useSyncExternalStore,
useTransition
} from './index';

export const REACT_ELEMENT_TYPE =
(typeof Symbol != 'undefined' && Symbol.for && Symbol.for('react.element')) ||
Expand Down Expand Up @@ -264,15 +283,29 @@ options.diffed = function (vnode) {
};

// This is a very very private internal function for React it
// is used to sort-of do runtime dependency injection. So far
// only `react-relay` makes use of it. It uses it to read the
// context value.
// is used to sort-of do runtime dependency injection.
export const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {
ReactCurrentDispatcher: {
current: {
readContext(context) {
return currentComponent._globalContext[context._id].props.value;
}
},
useCallback,
useContext,
useDebugValue,
useDeferredValue,
useEffect,
useId,
useImperativeHandle,
useInsertionEffect,
useLayoutEffect,
useMemo,
// useMutableSource, // experimental-only and replaced by uSES, likely not worth supporting
useReducer,
useRef,
useState,
useSyncExternalStore,
useTransition
}
}
};
19 changes: 19 additions & 0 deletions compat/test/browser/render.test.js
Expand Up @@ -544,4 +544,23 @@ describe('compat render', () => {

expect(scratch.textContent).to.equal('foo');
});

it("should support recoils's usage of __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED", () => {
// Simplified version of: https://github.com/facebookexperimental/Recoil/blob/c1b97f3a0117cad76cbc6ab3cb06d89a9ce717af/packages/recoil/core/Recoil_ReactMode.js#L36-L44
function useStateWrapper(init) {
const { ReactCurrentDispatcher } =
React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
const dispatcher = ReactCurrentDispatcher.current;
return dispatcher.useState(init);
}

function Foo() {
const [value] = useStateWrapper('foo');
return <div>{value}</div>;
}

React.render(<Foo />, scratch);

expect(scratch.textContent).to.equal('foo');
});
});

0 comments on commit 3123e7f

Please sign in to comment.