preactjs / signals

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

bug: signal.value in JSX does not trigger rerender using @preact/signals-react ^1.2.0 #298

Open izznatsir opened 1 year ago

izznatsir commented 1 year ago

Starting from @preact/signals-react@1.2.0, accessing signal value via signal.value in JSX does not trigger rerender when signal value is changed.

Reproduction: Stackblitz

izznatsir commented 1 year ago

If I change @vitejs/plugin-react jsxRuntime setting to classic and consequentially adding import * as React from 'react', it works as expected. But, React Refresh needs the jsxRuntime to be automatic. Doing this also fix #269, so these two issues might be related.

XantreDev commented 1 year ago

It works fine with @vitejs/plugin-react-swc, btw

spa5k commented 1 year ago

Any update on it? sadly i can't use the swc plugin of vite due to a bug in other lib

sbesh91 commented 1 year ago

This isn't an error with Signals exactly. The line of code signal.value++ does not trigger the setter. Try updating that to be signal.value += 1 and you'll see things work properly.

XantreDev commented 1 year ago

@sbesh91 Its not true. And i dont know any reason why ++ shouldn't trigger setter

https://stackblitz.com/edit/vitejs-vite-vtubyq?file=src/App.tsx

sbesh91 commented 1 year ago

@XantreGodlike well that's quite strange. I went ahead and forked that repro as well. It looks like the only difference here is on the button render. <button onClick={() => (count.value += 1)}>count is {count}</button> Tell you the truth, I'm not sure why binding it up like this forces a re-render and binding it up like your example <button onClick={() => (count.value += 1)}>count is {count.value}</button> doesn't trigger it.

You're also right that the ++ operator does fire the setter. Sorry for jumping to conclusions here.

https://stackblitz.com/edit/vitejs-vite-kbch31?file=src%2Fmain.tsx,src%2FApp.tsx

luisherranz commented 1 year ago

I've just noticed the same thing.

This is my reproduction: https://stackblitz.com/edit/vitejs-vite-csqbr6?file=src%2FApp.jsx


EDIT: I confirm that switching to jsxRuntime: 'classic' fixes the issue.

export default defineConfig({
  plugins: [
    react({
      jsxRuntime: 'classic',
    }),
  ],
});