mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
This is a simplified version of #1454. The goal of this PR is to inline the contents of `useMemo()` callbacks, rather than just immediately invoke the lambda. Turning useMemo() into an IIFE works, but it means that we can't optimize within the lambda block. Our investigations showed that there's a lot of room to optimize at a finer granularity than manually written useMemo calls. For example, one product instance had a useMemo that created a list of child JSX elements. Most of those elements only relied on a single variable (`a`), but a few relied on a second variable (`b). Thus _all_ elements were invalidated whenever `b` changed. If Forget retains the original lambda, we have no choice but to keep that (coarse) granularity for memoization. When we inline, we can optimize to make e.g. individual JSX elements depend on their precise dependencies. The rough idea is: * Keep track of all function expressions * When we find a useMemo, lookup its function expression, and add its CFG to the main function (the previous PR ensures that BlockIds won't collide) * Replace any return statements with a StoreLocal to save the result and a Goto to the code following the useMemo call. * Then we run the usual set of passes to patch the HIR back up again. Example: ```javascript // Before function Component(props) { const x = useMemo(() => { if (props.cond) { return null; } return foo(props.x); }, [props.x]); return x + props.y; } // Intended - **before** memoization function Component(props) { let x; if (props.cond) { x = null; } else { x = foo(props.x); } return x + props.y; } ```
test262
@ 83a46bfe0e
React Forget
React Forget is an experimental Babel plugin to automatically memoize React Hooks and Components.
Development
# tsc --watch
$ yarn dev
# in another terminal window
$ yarn test --watch
Notes
An overview of the implementation can be found in the Architecture Overview.
This transform
- needs plugin-syntax-jsx as a dependency to inherit the syntax from.
- should be run before plugin-transform-react-jsx
- assume the enforcement of rules of hooks, i.e.
- only call hooks from React functions
- only call hooks at the top level
- https://www.npmjs.com/package/eslint-plugin-react-hooks
Scaffolding
- https://github.com/facebook/flow/tree/master/packages/babel-plugin-transform-flow-enums
- https://github.com/babel/babel/blob/main/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts
Reference