In some cases, we need non-global atoms, useAtom hook will help in these cases, also it will help we have easy controlled/uncontrolled components
function useAtom<D>(init: D, upAtom?: RecoilState<D> | undefined | null): RecoilState<D> {
const [state] = useState(() => atom({
key: nanoid(), // random string
default: init,
}))
return upAtom ?? state
}
function Counter(props: { countAtom?: RecoilState<number> }) {
const countAtom = useAtom(0, props.countAtom)
const [count, setCount] = useRecoilState(countAtom);
const dec = () => {
setCount(c => c - 1)
}
const inc = () => {
setCount(c => c + 1)
}
return <span>
<button onClick={dec}>
-
</button>
{count}
<button onClick={inc}>
+
</button>
</span>;
}
const globalCountAtom = atom({
key: 'count', // unique ID (with respect to other atoms/selectors)
default: 0, // default value (aka initial value)
});
function CounterPage() {
const countAtom = useAtom(0)
return <div>
<h2>About </h2>
un controlled: <Counter/><br/>
<br/>
controlled
shared 1: <Counter countAtom={countAtom}/><br/>
shared 2: <Counter countAtom={countAtom}/><br/>
<br/>
global: <Counter countAtom={globalCountAtom}/><br/>
</div>
}
updates:
1- use initializer function in useState
2- useAtom arguments order changed
Hi @smmoosavi
To avoid creating a new atom on every render you could pass a function to useState so only one Atom is created.
function useAtom<D>(upAtom: RecoilState<D> | undefined | null, init: D): RecoilState<D> {
const [newAtom] = useState(() => atom({
key: nanoid(),
default: init,
}))
return upAtom ?? newAtom
}
@acutmore
change applied
Most helpful comment
Hi @smmoosavi
To avoid creating a new atom on every render you could pass a function to useState so only one Atom is created.