use-effect-event
Version:
Ponyfill of the experimental `React.useEffectEvent` hook
1 lines • 2.88 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/useEffectEvent.ts"],"sourcesContent":["import * as React from 'react'\n\nconst context = React.createContext(true)\n\nfunction forbiddenInRender() {\n throw new Error(\"A function wrapped in useEffectEvent can't be called during rendering.\")\n}\n\n// We can only check if we're in a render phase, beyond initial render, in React 19, with its `React.use` hook.\nconst isInvalidExecutionContextForEventFunction =\n 'use' in React\n ? () => {\n // There's no way to check if we're in a render phase from outside of React, the API used by useEffectEvent is private: https://github.com/facebook/react/blob/a00ca6f6b51e46a0ccec54a2231bfe7a1ed9ae1d/packages/react-reconciler/src/ReactFiberWorkLoop.js#L1785-L1788\n // So to emulate the same behavior, we call the use hook and if it doesn't throw, we're in a render phase.\n try {\n return React.use(context)\n } catch {\n return false\n }\n }\n : () => false\n\n/**\n * This is a ponyfill of the upcoming `useEffectEvent` hook that'll arrive in React 19.\n * https://19.react.dev/learn/separating-events-from-effects#declaring-an-effect-event\n * To learn more about the ponyfill itself, see: https://blog.bitsrc.io/a-look-inside-the-useevent-polyfill-from-the-new-react-docs-d1c4739e8072\n * @public\n */\nexport function useEffectEvent<const T extends (...args: any[]) => void>(fn: T): T {\n /**\n * For both React 18 and 19 we set the ref to the forbiddenInRender function, to catch illegal calls to the function during render.\n * Once the insertion effect runs, we set the ref to the actual function.\n */\n const ref = React.useRef(forbiddenInRender as T)\n\n React.useInsertionEffect(() => {\n ref.current = fn\n }, [fn])\n\n return ((...args: any) => {\n // Performs a similar check to what React does for `useEffectEvent`:\n // 1. https://github.com/facebook/react/blob/b7e2de632b2a160bc09edda1fbb9b8f85a6914e8/packages/react-reconciler/src/ReactFiberHooks.js#L2729-L2733\n // 2. https://github.com/facebook/react/blob/b7e2de632b2a160bc09edda1fbb9b8f85a6914e8/packages/react-reconciler/src/ReactFiberHooks.js#L2746C9-L2750\n if (isInvalidExecutionContextForEventFunction()) {\n forbiddenInRender()\n }\n\n const latestFn = ref.current!\n return latestFn(...args)\n }) as T\n}\n"],"names":["React"],"mappings":";;;;;;;;;;;;;;;;;;;AAEA,MAAM,UAAUA,iBAAM,cAAc,EAAI;AAExC,SAAS,oBAAoB;AAC3B,QAAM,IAAI,MAAM,wEAAwE;AAC1F;AAGA,MAAM,4CACJ,SAASA,mBACL,MAAM;AAGJ,MAAI;AACF,WAAOA,iBAAM,IAAI,OAAO;AAAA,EAAA,QAClB;AACN,WAAO;AAAA,EAAA;AAEX,IACA,MAAM;AAQL,SAAS,eAAyD,IAAU;AAKjF,QAAM,MAAMA,iBAAM,OAAO,iBAAsB;AAE/C,SAAAA,iBAAM,mBAAmB,MAAM;AAC7B,QAAI,UAAU;AAAA,EAAA,GACb,CAAC,EAAE,CAAC,GAEC,IAAI,SAAc;AAIpB,8CAAA,KACF,kBAAA;AAGF,UAAM,WAAW,IAAI;AACrB,WAAO,SAAS,GAAG,IAAI;AAAA,EAAA;AAE3B;;"}