Unexpected rerenders on derived atom #2714
-
I encountered a rerendering issue, and boiled it down to this simple recreation. I have list of items, from which I create an const items = [
{ id: 1, done: false, title: "apples" },
{ id: 2, done: false, title: "Flour" },
{ id: 3, done: false, title: "yeast" },
{ id: 4, done: true, title: "sugar" },
{ id: 5, done: true, title: "cinnamon" },
];
const itemsAtom = atom(items);
const itemAtomsAtom = atom((get) =>
get(itemsAtom).map((listItem) => atom(listItem))
);
const openItemAtomsAtom = atom((get) =>
get(itemAtomsAtom).filter((itemAtom) => !get(itemAtom).done)
); This setup works as expected and only rerenders the Item that was changed. However when I use the const itemAtoms = useAtomValue(itemAtomsAtom);
return (
<ul className="vstack">
{itemAtoms.map((atom) => (
<li key={atom.toString()} className="hstack">
{atom.toString()}
<Item itemAtom={atom} />
</li>
))}
</ul>
); What am I missing? I can't really use Here's the setup in a codesandbox: https://codesandbox.io/p/sandbox/jotai-derived-and-filtered-rerender-issue-j3f64x |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 6 replies
-
Can you try adding |
Beta Was this translation helpful? Give feedback.
If you change an item, it updates the atom of that list item (
atom(listItem)
).The
openItemAtomsAtom
depends on allatom(listItem)
s, so it will recompute whenever any item atom value changes, which triggers a re-render of the Open list component. And as mentioned by dmaskasky, React will then re-render all child components unless there are wrapped inReact.memo
.The
itemAtomsAtom
on the other hand only depends onitemsAtom
, which is never updated. It creates the individual item atoms but doesn't depend on them. And because of that,itemAtomsAtom
isn't recomputed when a single item atom changes. And that's why the All list component doesn't re-render when changing a single item.Hope it he…