Passing regular non-memoized selector to useStore
causes infinite re-renders
#3155
Answered
by
dai-shi
ansavchenco
asked this question in
Bug report
-
Bug DescriptionThe following simple example doesn't work and causes infinite re-renders. What am i doing wrong? import { create } from 'zustand';
type Item = { id: number; name: string };
type Store = {
itemsById: Record<Item['id'], Item>;
orderedIds: Item['id'][];
};
const items: Item[] = [
{ id: 1, name: 'One' },
{ id: 3, name: 'Three' },
{ id: 2, name: 'Two' },
];
const useStore = create<Store>(() => {
console.log('Initializing root store...');
const itemsById = items.reduce(
(acc, item) => ({ ...acc, [item.id]: item }),
{} as Store['itemsById']
);
const orderedIds = Object.values(itemsById)
.sort((a, b) => a.id - b.id)
.map((item) => item.id);
return {
itemsById,
orderedIds,
};
});
export function App() {
console.log('re-render');
// this causes infinite re-render
const store = useStore((state) =>
state.orderedIds.map((id) => state.itemsById[id])
);
// this works
// const store = useStore();
// const items = store.orderedIds.map((id) => store.itemsById[id]);
return (
<div>
<h1>Hello</h1>
<pre>{JSON.stringify(store, null, 2)}</pre>
{/* <pre>{JSON.stringify(items, null, 2)}</pre> */}
</div>
);
} Reproduction Linkhttps://stackblitz.com/edit/vitejs-vite-unwlyecd?file=src%2FApp.tsx |
Beta Was this translation helpful? Give feedback.
Answered by
dai-shi
Jun 17, 2025
Replies: 1 comment
-
Try this: - const store = useStore((state) =>
+ const store = useStore(useShallow((state) =>
state.orderedIds.map((id) => state.itemsById[id])
- );
+ )); |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
ansavchenco
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Try this: