expose "get" on useRecoilCallback
See original GitHub issueHi folks, i’m using useRecoilCallback for running tasks.
it may be needed during a task to get the last updated value of an atom
why not espose the “get” function ?
function get(recoilState) {
return getRecoilValueAsLoadable(storeRef.current, recoilState);
}
i’m currently use a fake get (that i suppose is safe because enqueue updaters) that is OK.
const counter = atom({
key: "counter",
default: 0,
});
const injectGet = (set) => (recoilState) => {
return new Promise((resolve) => {
set(recoilState, (prev: unknown) => {
resolve(prev); //TODO handle lodables
return prev;
});
});
};
export const useTestTask = () =>
useRecoilCallback(({ snapshot, set}) => async () => {
const get = injectGet(set);
for (let i = 0; i < 20; i++) {
let current = await get(counter);
let old = await snapshot.getLoadable(counter).toPromise();
console.log("current, old ", current, old);
set(counter, inc);
}
},
[]
);
But there is a problem if i want to read from async selectors:
const counterSelector= selector({
key:"counterSelector",
get: async ({get})=> get(counter)
})
export const useTestTask2 = () =>
useRecoilCallback(({ snapshot, set}) => async () => {
const get = injectGet(set);
for (let i = 0; i < 20; i++) {
let current = await get(counterSelector);
let old = await snapshot.getLoadable(counterSelector).toPromise();
console.log("current, old ", current, old);
set(counter, inc);
}
},
[]
);
//"cannot set selector while it is pending...."
Patching useRecoilCallback and expose real get solve all the problems
function useRecoilCallback<Args: $ReadOnlyArray<mixed>, Return>(
fn: CallbackInterface => (...Args) => Return,
deps?: $ReadOnlyArray<mixed>,
): (...Args) => Return {
const storeRef = useStoreRef();
const gotoSnapshot = useGotoRecoilSnapshot();
return useCallback(
(...args): Return => {
// Use currentTree for the snapshot to show the currently committed state
const snapshot = cloneSnapshot(storeRef.current);
function set<T>(
recoilState: RecoilState<T>,
newValueOrUpdater: (T => T) | T,
) {
setRecoilValue(storeRef.current, recoilState, newValueOrUpdater);
}
function reset<T>(recoilState: RecoilState<T>) {
setRecoilValue(storeRef.current, recoilState, DEFAULT_VALUE);
}
///patch
function get(recoilState) {
return getRecoilValueAsLoadable(storeRef.current, recoilState);
}
/// ....
}
All ok now:
export const useTestTask3 = () =>
useRecoilCallback(({ snapshot, set, get}) => async () => {
for (let i = 0; i < 20; i++) {
let current = await get(counterSelector).toPromise();
let old = await snapshot.getLoadable(counterSelector).toPromise();
console.log("current, old ", current, old);
set(counter, inc);
}
},
[]
);
Any thoughts?
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (3 by maintainers)
Top Results From Across the Web
useRecoilCallback(callback, deps) | Recoil
Asynchronously read Recoil state without subscribing a React component to re-render if the atom or selector is updated. Deferring expensive lookups to an...
Read more >Create and Read State for thousands of items using Recoil
To Save the data, I have a button which calls a function. That function just needs to get the ID's, loop through them,...
Read more >recoil | Yarn - Package Manager
Workaround for React 18 environments with nested renderers that don't support useSyncExternalStore() (#2001, #2010); Expose flag to disable "duplicate atom ...
Read more >How to update atoms (state) in Recoil.js outside components ...
<RecoilExternalStatePortal> must have been previously loaded in the React tree, ... because it's not temporally dependent like "get" is useRecoilCallback(({ ...
Read more >Managing Complex State in React with Jared Palmer [explicit]
You should never have State in two places at any time. ... That's going to be scoped and encapsulated but don't expose public...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Wow, thanks @BenjaBobs, that’s exactly what I was after! I should have realized that
snapshot
has agetLoadable()
method.For reference, here’s what I ended up with:
@drarmstr i understand your motivation, but i’m very happy that there is a way to get current state while running tasks, if needed in advanced tasks. (like redux-saga does) Because it would be a limitation for the great power of recoil! Thank you!