-
I use atomFamily/selectorFamily a lot within Recoil. Is there any recommended way to use atom with param to replace Recoil's atomFamily instead of Jotai's atomFamily? I read here and there people mentioning about that but couldn't really find it. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 6 replies
-
I usually wouldn't use To help your use case, is it possible for you to create a smallest possible example to show your expectation? Maybe we can start with a simple one, like transforming one Recoil's atomFamily to Jotai's atomFamily. |
Beta Was this translation helpful? Give feedback.
-
Example 0: selectorFamily onlyexport const rAtmFamItemTodo = selectorFamily({
key: 'selectorFamilyAtomFamilyItemTodo',
get:
(_id) =>
({ get }) => {
const itemTodo = get(rAtmTodos).find(
(itemTodo) => itemTodo._id === _id
);
return {
...itemTodo!,
};
},
}); The Jotai version would be: export const rAtmFamItemTodo = atomFamily((_id: Todos['_id']) => atom(
(get) => {
const itemTodo = get(rAtmTodos).find(
(itemTodo) => itemTodo._id === _id
);
return {
...itemTodo!,
};
}
)); I don't like copying the item object, so I would do: export const rAtmFamItemTodo = atomFamily((_id: Todos['_id']) => atom(
(get) => {
const itemTodo = get(rAtmTodos).find(
(itemTodo) => itemTodo._id === _id
);
return itemTodo || {};
}
)); which can be simplified to: export const rAtmFamItemTodo = atomFamily((id: Todos['_id']) => atom(
(get) => get(rAtmTodos).find(({ _id }) === id) || {}
)); I wouldn't use Because picking a todo from todos is a lightweight task, we don't even need to cache the result across components. export const selectTodoAtom = (id: Todos['_id']) => atom(
(get) => get(rAtmTodos).find(({ _id }) === id) || {}
)); And, use it in a component with useMemo: const Component = ({ id }) => {
const todo = useAtomValue(useMemo(() => selectTodoAtom(id), [id]));
...
} And, it's memory leak free. |
Beta Was this translation helpful? Give feedback.
-
Example 1: atomFamily with selectorFamily defaultexport const rAtmFamItemTodo = atomFamily<Todos, Todos['_id']>({
key: 'rAtmFamItemTodo',
default: selectorFamily({
key: 'selectorFamilyAtomFamilyItemTodo',
get:
(_id) =>
({ get }) => {
const itemTodo = get(rAtmTodos).find(
(itemTodo) => itemTodo._id === _id
);
return {
...itemTodo!,
};
},
cachePolicy_UNSTABLE: {
eviction: 'most-recent',
},
}),
}); Jotai has only one non-configurable cache policy. The Jotai version would be: export const rAtmFamItemTodo = atomFamily((_id: Todos['_id']) => atomWithDefault(
(get) => get(rAtmTodos).find(({ _id }) === id) || {}
)); assuming we don't need to copy object, and simplified. |
Beta Was this translation helpful? Give feedback.
-
Example 2: atomFamily with atom effectsexport const rAtmFamMinimumMediaQuery = atomFamily<boolean, number>({
key: 'rAtmFamMinimumMediaQuery',
default: false,
effects: (mediaQueryValue) => [
({ setSelf, resetSelf }) => {
if (typeof window === 'undefined') return;
const windowMediaQueries = () => {
if (window.innerWidth > mediaQueryValue) {
setSelf(true);
} else {
resetSelf();
}
};
windowMediaQueries();
window.addEventListener('resize', windowMediaQueries);
return () => {
window.removeEventListener('resize', windowMediaQueries);
};
},
],
}); Jotai doesn't have Recoil's atom effects as a design choice, but has The Jotai version would be: export const rAtmFamMinimumMediaQuery = atomFamily((mediaQueryValue: number) => {
const boolAtom = atom(false);
boolAtom.onMount = (set) => {
if (typeof window === 'undefined') return;
const windowMediaQueries = () => {
if (window.innerWidth > mediaQueryValue) {
set(true);
} else {
set(false);
}
};
windowMediaQueries();
window.addEventListener('resize', windowMediaQueries);
return () => {
window.removeEventListener('resize', windowMediaQueries);
};
};
return boolAtom;
}); We could use I'd prefer it a little shorter: export const rAtmFamMinimumMediaQuery = atomFamily((mediaQueryValue: number) => {
const boolAtom = atom(false);
boolAtom.onMount = (set) => {
if (typeof window === 'undefined') return;
const windowMediaQueries = () => set(window.innerWidth > mediaQueryValue);
windowMediaQueries();
window.addEventListener('resize', windowMediaQueries);
return () => window.removeEventListener('resize', windowMediaQueries);
};
return boolAtom;
}); |
Beta Was this translation helpful? Give feedback.
#1323 (reply in thread)
Example 0: selectorFamily only
The Jotai version would be:
I don't like copying the item object, so I would do: