Recoil: `useAtom` hook for short life atoms, and

Created on 31 May 2020  路  2Comments  路  Source: facebookexperimental/Recoil

Idea

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

defination

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
}

usage

live demo

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

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.

function useAtom<D>(upAtom: RecoilState<D> | undefined | null, init: D): RecoilState<D> {
    const [newAtom] = useState(() => atom({
        key: nanoid(),
        default: init,
    }))
    return upAtom ?? newAtom
}

All 2 comments

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

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tklepzig picture tklepzig  路  3Comments

thegauravthakur picture thegauravthakur  路  3Comments

pesterhazy picture pesterhazy  路  4Comments

jamiebuilds picture jamiebuilds  路  3Comments

jamiewinder picture jamiewinder  路  3Comments