Observing value using array include method #187
-
I'm trying to understand why it renders all list items if i update one check box?? I tried using import { enableReactUse } from '@legendapp/state/config/enableReactUse';
import { observable } from '@legendapp/state';
import { useSelector } from '@legendapp/state/react';
enableReactUse();
const list = Array.from({ length: 5 }, (_, i) => i + 1);
const state = observable({ selection: [] as number[] });
const ListItem = ({ id }: { id: number }) => {
// const checked = state.selection.use().includes(id);
const checked = useSelector(() => state.selection.get().includes(id));
console.log(checked, id);
return (
<label>
<input
type='checkbox'
checked={checked}
onChange={() => {
state.selection.set((prev) => {
const arr = [...prev];
if (arr.includes(id)) return arr.filter((item) => item !== id);
return [...arr, id];
});
}}
/>
<span>{id}</span>
</label>
);
};
const App = () => {
return (
<div>
{list.map((id) => (
<ListItem key={id} id={id} />
))}
</div>
);
};
export default App; |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
Sorry about missing this! There was a bug in useSelector where it was re-rendering even if the return value was unchanged. That should be fixed now in the latest version. Also, for what it's worth, the selection setting could be optimized - that checks all elements in the array twice (includes and filter) and allocates four new arrays. It would be better (and shorter) to use splice directly on the observable: const index = state.selection.indexOf(id);
if (index >= 0) {
state.selection.splice(index, 1);
} But actually, it would be much more efficient as a Set: // Create state with Set
const state = observable({ selection: new Set<string>() });
// Getting value is constant time
const checked = useSelector(() => state.selection.get().has(id));
// Then to remove is just a delete
state.selection.delete(id); |
Beta Was this translation helpful? Give feedback.
Sorry about missing this!
There was a bug in useSelector where it was re-rendering even if the return value was unchanged. That should be fixed now in the latest version.
Also, for what it's worth, the selection setting could be optimized - that checks all elements in the array twice (includes and filter) and allocates four new arrays. It would be better (and shorter) to use splice directly on the observable:
But actually, it would be much more efficient as a Set: