LegendApp / legend-state

Legend-State is a super fast and powerful state library that enables fine-grained reactivity and easy automatic persistence
https://legendapp.com/open-source/state/
MIT License
2.71k stars 80 forks source link

onChange from computed does not fire #331

Open lishine opened 1 month ago

lishine commented 1 month ago

https://stackblitz.com/edit/vitejs-vite-pttjkv?file=src%2FApp.tsx,package.json

import { computed, observable } from '@legendapp/state';
import { observer } from '@legendapp/state/react';
const plugins$ = observable([
  { tabs: [{ a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }, { a: 1 }] },
]);
const pluginsComputed$ = computed(() => {
  console.log('in pluginsComputed');
  return plugins$.get().map((a) => a);
});
plugins$[0].tabs.onChange(() => {
  console.log('plugins$[0].tabs onchange');
});
pluginsComputed$[0].tabs.onChange(() => {
  console.log('pluginsComputed$[0].tabs onchange');
});
setTimeout(() => {
  plugins$[0].tabs.push({ a: 1 });
}, 2000);

You won't see this console log: "pluginsComputed$[0].tabs onchange" This is the bahaviour in v2 as well

lishine commented 1 month ago

I think this is same as: https://github.com/LegendApp/legend-state/issues/305 A blocker. Am I doing something wrong?

yardenxr commented 1 month ago

I have the exact same issue. In general, the array’s behavior is very odd in the legend app. i had a few problems where i had to convert my Array into Record in order to stay reactive.

noamikoko commented 1 month ago

I believe I have the same issue, I am using an array of objects and one of the fields in that object is also an array, That field is not reactive

Anyone have a workaround which is not simply adding a get to the root of add a onChange callback ?

jmeistrich commented 1 month ago

Thanks @lishine, I pasted that into a test and it's definitely an issue. I'll look into it.

@noamikoko and @yardenxr is it the same for you having a computed function pointing into an array? Or is it just a regular observable array?

noamikoko commented 1 month ago

Yes, in a computed

yardenxr commented 1 month ago

@jmeistrich exactly the same issue, inside a computed function.

lishine commented 4 weeks ago

Simply creating a new array inside computed (destructuring/map etc.) instead of returnin an existing array value from observable - will make the computed not reactive.

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