-
Notifications
You must be signed in to change notification settings - Fork 47k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Fresh] Generate signatures for Hooks #15733
Conversation
This currently only works one level deep. For custom Hooks, we'll need to add some way to compose signatures.
This prevents a class of problems where other plugins cause our visitor to re-run. It's a standard Babel practice, e.g.: https://github.com/babel/babel/blob/8c7d4b55c99ff34cb9d493d452472e59b5ed1e70/packages/babel-plugin-transform-react-constant-elements/src/index.js#L85-L86
case 'useCallback': | ||
case 'React.useCallback': | ||
case 'useImperativeMethods': | ||
case 'React.useImperativeMethods': |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the decision to omit useRef
, useContext
, and useDebugValue
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I forgot about them lol
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😂
// let Foo = () => {} | ||
// let Foo = function() {} | ||
// We'll register it on next line so that | ||
// we don't mess up the inferred 'Foo' function name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice.
).toMatchSnapshot(); | ||
}); | ||
|
||
it('includes custom hooks into the signatures', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice
@@ -1,5 +1,61 @@ | |||
// Jest Snapshot v1, https://goo.gl/fbAQLP | |||
|
|||
exports[`ReactFreshBabelPlugin generates signatures for function declarations calling hooks 1`] = ` | |||
" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can use https://www.npmjs.com/package/jest-snapshot-serializer-raw to avoid the escaped "
and extra wrapping "
. We've done the same in Jest: jestjs/jest#7651
Makes them a bit easier to read, IMO 🙂
EDIT: Simple enough to PR, so I did: #15806
* Generate signatures for Hooks This currently only works one level deep. For custom Hooks, we'll need to add some way to compose signatures. * Be more resilient to plugin conflicts This prevents a class of problems where other plugins cause our visitor to re-run. It's a standard Babel practice, e.g.: https://github.com/babel/babel/blob/8c7d4b55c99ff34cb9d493d452472e59b5ed1e70/packages/babel-plugin-transform-react-constant-elements/src/index.js#L85-L86 * Remove unnecessary stuff from debugging * Include Foo.useHookName() calls into the signature * Add an integration test for adding/removing an effect * Add integration test for changing custom Hook order * Include custom Hooks into the signatures * Fix inferred names for function expressions * Support export default hoc(Foo) when Foo is defined separately * Add more built-in Hooks
* Generate signatures for Hooks This currently only works one level deep. For custom Hooks, we'll need to add some way to compose signatures. * Be more resilient to plugin conflicts This prevents a class of problems where other plugins cause our visitor to re-run. It's a standard Babel practice, e.g.: https://github.com/babel/babel/blob/8c7d4b55c99ff34cb9d493d452472e59b5ed1e70/packages/babel-plugin-transform-react-constant-elements/src/index.js#L85-L86 * Remove unnecessary stuff from debugging * Include Foo.useHookName() calls into the signature * Add an integration test for adding/removing an effect * Add integration test for changing custom Hook order * Include custom Hooks into the signatures * Fix inferred names for function expressions * Support export default hoc(Foo) when Foo is defined separately * Add more built-in Hooks
This adds support for editing components with Hooks.
State preservation already works by default. The goal here is to not preserve state in cases where it is known to lead to problems. Such as reordering or deleting Hooks. We want to detect when that happens and remount.
This is implemented by generating
__signature__
calls for functions that contains calls to Hooks:If a signature changes, the Fresh runtime will tell React to remount that component type.
The signature contains names of all Hooks. Hooks that have a left hand side like
const [foo, setFoo]
have its source embedded in the signature. This catches renames (which often indicate invasive edits like changing state variable type).If you use custom Hooks, we add them as the last argument:
This lets us recurse into each custom Hook when comparing signatures, so that if
useMyStuff
itself gets edited, we can remount the components using it.The last argument is lazily evaluated (a function) for two reasons:
The PR is easier to read without whitespace because some logic moved. You might also want to check commits separately.