Recoil is a shared state between components
How to create shared state between components (Atom)?
useRecoilState is like useState but useRecoilState can be used to access/ update state from different components
// Define a shared state const fontSizeState = atom({ key: 'fontSizeState', default: 14, }); // FontButton component accesses this state and update it function FontButton() { const [fontSize, setFontSize] = useRecoilState(fontSizeState); return ( <button onClick={() => setFontSize((size) => size + 1)} style={{fontSize}}> Click to Enlarge </button> ); } // Text component is also able to access this state (or of course to update it too) function Text() { const [fontSize, setFontSize] = useRecoilState(fontSizeState); return <p style={{fontSize}}>This text will increase in size too.</p>; }
How to create read only shared state basing on Atom state?
Use selectors. Selector takes Atom state as input and returns a formatted value as output.
// fontSizeLabelState selector takes fontSizeState as input // fontSizeLabelState returns a formatted font size label as output const fontSizeLabelState = selector({ key: 'fontSizeLabelState', get: ({get}) => { const fontSize = get(fontSizeState); const unit = 'px'; return `${fontSize}${unit}`; }, }); // FontButton component accesses fontSizeLabelState selector // Clicking on the button does two things: // - increases the font size of the button // - while also updating the font size label function FontButton() { const [fontSize, setFontSize] = useRecoilState(fontSizeState); const fontSizeLabel = useRecoilValue(fontSizeLabelState); return ( <> <div>Current font size: ${fontSizeLabel}</div> <button onClick={() => setFontSize(fontSize + 1)} style={{fontSize}}> Click to Enlarge </button> </> ); }
How to get Recoil state in a custom hook?
Since recoil only subscribe and update those values inside react component, useRecoilState
and useRecoilValue
hook don’t work properly in custom hooks.
We will have to update the value by ourselves.
import { useEffect, useRef } from 'react'; import { useRecoilState } from 'recoil'; import { someAtom } from './recoilstates/someState'; const yourCustomHook = () => { const [someState, setSomeState] = useRecoilState(someAtom); const latestSomeState = useRef(someState); useEffect(()=> { latestSomeState.current = someState; },[someState]); // I use useEffect here as an example, // custom hook can contain any React hooks useEffect(()=>{ // your custom hook logic here // use latestSomeState.current for latest value }); }
Leave a Reply