Recoil atom effects
Atle Frenvik Sveen
Posted on February 24, 2023
..are effing cool!
I've been using Recoil.js for a while now, but I've never taken the time to dive into atom effects before recently.
Why did I do so? Because I needed a timer. Or a clock if you will. Running in recoil. And atom effects seems to do the trick. Just look here
import {AtomEffect, atomFamily} from 'recoil';
export type Millisecounds = number;
const getUnixNow = () => Math.floor(Date.now() / 1000);
const clockEffect =
(interval: Millisecounds): AtomEffect<number> =>
({setSelf, trigger}) => {
if (trigger === 'get') {
setSelf(getUnixNow());
}
const timer = setInterval(() => setSelf(getUnixNow()), interval);
return () => clearInterval(timer);
};
/**
* Atom that contains the current unix timestamp
* Updates at the provided interval
*/
export const clockState = atomFamily<number, Millisecounds>({
key: 'clockState',
default: getUnixNow(),
effects: (interval: Millisecounds) => [clockEffect(interval)],
});
This gives you an atomFamiliy that can be instantiated with the desired interval, and this atom automagically updates each interval, in this case returning the current unix timestamp
const time = useRecoilValue(clockState(1000)); //new clock state that updates every secound
return <div>The current Unix time is now: {time}</div>
Neat?
Well. But what you can do is use this as a trigger in a selector that needs to run periodically
export const pollerState = selector<SomeData[]>({
key: 'pollerState ',
get: async ({get}) => {
//add this to referesh every minute
get(clockState(60000));
return await myApi.getSomeData();
},
});
And this is pretty neat!
And if this doesn't get you hooked on atom effects, take a look at this, straight outta the recoil docs (Just some TypeScript added):
export const localStorageEffect =
<T>(key: string): AtomEffect<T> =>
({setSelf, onSet}) => {
const savedValue = localStorage.getItem(key);
if (savedValue != null) {
setSelf(JSON.parse(savedValue));
}
onSet((newValue, _, isReset) => {
isReset ? localStorage.removeItem(key) : localStorage.setItem(key, JSON.stringify(newValue));
});
};
const syncedState = atom<string>({
key: 'syncedState',
default: '',
effects: [localStorageEffect('local_storage_key')],
});
This actually syncs your atom to local storage. Sweet!
Posted on February 24, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.