Last active
October 19, 2020 06:51
-
-
Save NoriSte/e914c58d37ab6b34c5b962c169392ca4 to your computer and use it in GitHub Desktop.
Re-implementing Recoil APIs / article gists
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// @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