70 %

recoiljs


RecoilJS is a state lib that promotes a data-flow graph.

7 guis

I built out a set of examples comparing Recoil to regular React

Notes

You need a RecoilRoot

JS
import React from 'react';
import {
RecoilRoot,
atom,
selector,
useRecoilState,
useRecoilValue,
} from 'recoil';
function App() {
return (
<RecoilRoot>
<CharacterCounter />
</RecoilRoot>
);
}

Atoms are built using a function and are the fundamental unit of recoil

JS
const textState = atom({
key: 'textState', // unique ID (with respect to other atoms/selectors)
default: '', // default value (aka initial value)
});

useRecoilState functions similarly to useState

JS
const [text, setText] = useRecoilState(textState);

There is a corresponding hook for if you want to "only read": useRecoilValue.

JS
const count = useRecoilValue(charCountState);

Selectors take atoms as arguments. If you use a selector and get another value in the getter of that selector you'll see a setState warning that won't currently affect program operation.

textState-atom
JS
const charCountState = selector({
key: 'charCountState', // unique ID (with respect to other atoms/selectors)
get: ({get}) => {
const text = get(textState);
return text.length;
},
});

useRecoilCallback seems like a way to call async functions from render based on props? It can get an async atom value as a promise.

useRecoilStateLoadable is a big ? feels. Something to do with Suspense ish.

vocabulary

  • RecoilRoot: Similar to a context provider. Needs to be "above" anything that uses recoil
  • atoms: importable, updatable values that get be primitive, derived, or async
  • selector: derived state. A way of accessing an atom.
  • Loadable: Some kind of Suspense-compatible async value that looks like:
JS
{
state: ?,
getValue() {},
toPromise() {}
}

this hook will not throw a Promise when reading from a pending asynchronous selector (for the purpose of working alongside Suspense)

Example App

JS
import {atom, selector, useRecoilState} from 'recoil';
const tempFahrenheit = atom({
key: 'tempFahrenheit',
default: 32,
});
const tempCelcius = selector({
key: 'tempCelcius',
get: ({get}) => ((get(temptempFahrenheit) - 32) * 5) / 9,
set: ({set}, newValue) => set(tempFahrenheit, (newValue * 9) / 5 + 32),
});
function TempCelcius() {
const [tempF, setTempF] = useRecoilState(tempFahrenheit);
const [tempC, setTempC] = useRecoilState(tempCelcius);
const addTenCelcius = () => setTempC(tempC + 10);
const addTenFahrenheit = () => setTempF(tempF + 10);
return (
<div>
Temp (Celcius): {tempC}
<br />
Temp (Fahrenheit): {tempF}
<br />
<button onClick={addTenCelcius}>Add 10 Celcius</button>
<br />
<button onClick={addTenFahrenheit}>Add 10 Fahrenheit</button>
</div>
);
}