Skip to content

Instantly share code, notes, and snippets.

@NoriSte
Last active October 19, 2020 06:51
Show Gist options
  • Save NoriSte/e914c58d37ab6b34c5b962c169392ca4 to your computer and use it in GitHub Desktop.
Save NoriSte/e914c58d37ab6b34c5b962c169392ca4 to your computer and use it in GitHub Desktop.
Re-implementing Recoil APIs / article gists
// @see https://github.com/NoriSte/recoil-apis
/**
* Recoil-like atom creation.
*/
export const atom = <T>(atom: Atom<T>) => {
// ...
return atom;
};
/**
* Recoil-like selector creation.
*/
export const selector = <T>(selector: Selector<T>) => {
// ...
return selector;
};
/**
* Subscribe to all the Recoil Values updates and return the current value.
*/
export const useRecoilValue = <T>(recoilValue: RecoilValue<T>) => {
const recoilId = useRecoilId();
const [, forceRender] = useReducer((s) => s + 1, 0);
// registering a Recoil value requires the recoil id (stored in a React Context),
// That's why it can't be registered outside a component/hook code. `registerRecoilValue`
// must be idempotent
registerRecoilValue(recoilId, recoilValue);
useSubscribeToRecoilValues(recoilValue, forceRender);
return coreGetRecoilValue(recoilId, recoilValue);
};
/**
* Subscribe to all the Recoil Values updates and return both the current value and a setter.
*/
export const useRecoilState = <T>(recoilValue: RecoilValue<T>) => {
const recoilId = useRecoilId();
const currentValue = useRecoilValue(recoilValue);
if (isAtom(recoilValue)) {
const setter = createPublicSetAtomValue(recoilId, recoilValue);
return [currentValue, setter] as const;
} else {
const setter = (nextValue: T) => {
if (recoilValue.set)
recoilValue.set(
{
get: createPublicGetRecoilValue(recoilId),
set: createPublicSetRecoilValue(recoilId)
},
nextValue
);
};
return [currentValue, setter] as const;
}
};
/**
* Get the Recoil id of the current components tree.
*/
const useRecoilId = () => {
const recoilId = useContext(RecoilContext);
if (!recoilId) {
throw new Error("Wrap your app with <RecoilRoot>");
}
return recoilId;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment