preactjs / signals

Manage state with style in every framework
https://preactjs.com/blog/introducing-signals/
MIT License
3.71k stars 91 forks source link

Add package `@preact/signals-react-transform` #375

Closed andrewiggins closed 1 year ago

andrewiggins commented 1 year ago

This PR adds a new package @preact/signals-react-transform that provides a Babel plugin to transform functions to observer/track what signals are used when the function runs. This plugin is the start to an alternate React integration for signals that does not hook into React internals. Once our approach here is finalized and published, I'll update the @preact/signals-react package to reference this and provide various options for using signals in React.

Check the test file for examples of what the transformation looks like.

I'm currently exploring two different kinds of transformations in this implementation to see which one works better. One just adds a call to useSignals() to the top of the component and relies on the next invocation of useSignals or a microtick to stop tracking signals. The other wraps the component body in a try/finally to start and stop tracking signals. I'm currently leaning towards making the try/finally the default cuz it leaves less room for tricky edge cases that may lead to non-obvious behavior and rerenders.

However, the implementation of useSignals is the same either way. We'll always setup the microtick to clean up any outstanding effects to prevent any loose ends regardless of which transformation is used. So users can manually drop useSignals into a component and get basic functionality.

changeset-bot[bot] commented 1 year ago

đŸĻ‹ Changeset detected

Latest commit: 255208abf700d26eee8071f2d630f6efc730a514

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages | Name | Type | | ------------------------------- | ----- | | @preact/signals-react | Patch | | @preact/signals-react-transform | Patch |

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

netlify[bot] commented 1 year ago

Deploy Preview for preact-signals-demo ready!

Name Link
Latest commit 255208abf700d26eee8071f2d630f6efc730a514
Latest deploy log https://app.netlify.com/sites/preact-signals-demo/deploys/64cad3e1ec66ea00087a05d6
Deploy Preview https://deploy-preview-375--preact-signals-demo.netlify.app
Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

github-actions[bot] commented 1 year ago

Size Change: +267 B (0%)

Total Size: 78 kB

Filename Size Change
docs/dist/assets/client.********.js 46.7 kB +95 B (0%)
docs/dist/react-********.js 238 B -1 B (0%)
packages/react/dist/signals.js 1.35 kB +89 B (+7%) 🔍
packages/react/dist/signals.mjs 1.29 kB +84 B (+7%) 🔍
ℹī¸ View Unchanged | Filename | Size | | :--- | :---: | | `docs/dist/assets/index.********.js` | 835 B | | `docs/dist/assets/jsxRuntime.module.********.js` | 281 B | | `docs/dist/assets/preact.module.********.js` | 4.02 kB | | `docs/dist/assets/signals-core.module.********.js` | 1.43 kB | | `docs/dist/assets/signals.module.********.js` | 2.02 kB | | `docs/dist/assets/style.********.js` | 21 B | | `docs/dist/assets/style.********.css` | 1.21 kB | | `docs/dist/basic-********.js` | 244 B | | `docs/dist/demos-********.js` | 3.35 kB | | `docs/dist/nesting-********.js` | 1.13 kB | | `packages/core/dist/signals-core.js` | 1.5 kB | | `packages/core/dist/signals-core.mjs` | 1.53 kB | | `packages/preact/dist/signals.js` | 1.27 kB | | `packages/preact/dist/signals.mjs` | 1.22 kB | | `packages/react-transform/dist/signals-*********.js` | 2.79 kB | | `packages/react-transform/dist/signals-transform.mjs` | 2.66 kB | | `packages/react-transform/dist/signals-transform.umd.js` | 2.91 kB |

compressed-size-action

andrewiggins commented 1 year ago

TODO for myself: Add some E2E babel transform tests, i.e. transform code and run it. Done

XantreDev commented 1 year ago

What if someone calls useSignals twice? Or babel will add additional one?

XantreDev commented 1 year ago

What about cases when signals used inside hooks that component uses? How to handle this case?

andrewiggins commented 1 year ago

What if someone calls useSignals twice? Or babel will add additional one?

useSignals can be called multiple times in a component. It'll recreate the effect and other relevant tracking machinery but that's okay. The previous effect will be cleaned up and any signals used after the additional calls to useSignals will still trigger rerenders properly.

What about cases when signals used inside hooks that component uses? How to handle this case?

Hooks that use signals are transformed to call useSignals at the top of the function. In this situation, we are relying on the fact that calling useSignals multiple times is safe to do.