-
If you are familiar with Jotai API, you will notice that there's no way to update atom values imperatively when some other atoms change. This is intentional because such imperative logic is not declarative, and it's not aline with Jotai atom abstraction, which is declarative or "pure". The canonical solution for imperative updates is: But, if we give up pure atom model, would we be able to update imperatively somehow? Let's explore some hacks. Note that this is far from recommendation. 1st iteration: export function atomWithImperativeUpdate(fn) {
const setterAtom = atom(null);
const baseAtom = atom(
(get) => {
const setter = get(setterAtom)?.[0];
if (setter) {
fn(get, setter);
return true;
}
return false;
},
(get, set, isInit) => {
if (isInit) {
set(setterAtom, [set]);
} else {
set(setterAtom, null);
}
},
);
baseAtom.onMount = (init) => {
init(true);
return () => init(false);
};
const derivedAtom = atom((get) => get(baseAtom));
return derivedAtom;
} |
Beta Was this translation helpful? Give feedback.
Replies: 6 comments 22 replies
-
Starting this sub-thread to centralize a bunch of code updates. It works! Please see the code sandbox demo, https://codesandbox.io/s/jotai-forked-69lvfr |
Beta Was this translation helpful? Give feedback.
-
Add cleanup function. export function atomWithImperativeUpdate(fn) {
const setterAtom = atom(null);
+ const cleanupAtom = atom(null);
const baseAtom = atom(
(get) => {
const setter = get(setterAtom)?.[0];
if (setter) {
+ get(cleanupAtom)?.();
+ const cleanup = fn(get, setter);
+ setter(cleanupAtom, () => cleanup);
return true;
}
return false;
},
(get, set, isInit) => {
if (isInit) {
set(setterAtom, [set]);
} else {
set(setterAtom, null);
}
},
);
baseAtom.onMount = (init) => {
init(true);
return () => init(false);
};
const derivedAtom = atom((get) => get(baseAtom));
return derivedAtom;
} |
Beta Was this translation helpful? Give feedback.
-
Opening a new thread for some responses:
Yeah, I believe the current impl batches a single
I'm not 100% following, but if it's always with a delay, can we simply use
Yes, that sounds good, but let's defer the final decision.
btw, if you returns a promise from the read function, Jotai will update atom's dependencies on resolve. Not sure if it helps.
Again, that sounds like we could use |
Beta Was this translation helpful? Give feedback.
-
Yeah, we could do something like this. It's another hack, but it also works. I don't have a strong preference. const anAtom = atom(
(get, { setSelf }) => {
queueMicrotask(() => {
setSelf((get, set) => effectFn(get, set));
});
},
(get, set, writeFn) => writeFn(get, set);
); Please note that the above code lacks a number of critical elements:
|
Beta Was this translation helpful? Give feedback.
-
Could atomWithBroadcast be used for this purpose? |
Beta Was this translation helpful? Give feedback.
https://github.com/jotaijs/jotai-effect