In Webiny we have the Page Builder Application that was built with help of redux as global state management. We decided to switch our Page Builder to Recoil due to redux being hard to maintain and debug. But before we dive into how we did it, what were the issues and how we managed to make everything work with our code structure, a bit info about ...
Recoil
It is a, fairly new, library for managing global state - like redux. It is being developed by people at Facebook and it is still in an experimental state, so you can expect things will change.
Introduction
A recoil state is contained within an atom. The official description says an atom is “a representation of the state”. You can have multiple atoms, to split state, e.g. page, content, UI, etc., which helps when structuring the actual state. It can lead to some problems though, but we will come to that later.
Recoil is used via hooks, so you can not use it in your class components. If you would like to use Recoil, and you have class components, you need to wrap your class component in a function one and pass the Recoil state and state set function.
Basic Recoil API info
Atom
“An atom represents a state in Recoil”, says the official documentation about it. Look at it as part of the global state object from redux. Of course, you can put everything in a single atom, but we reckon that is not the intended use. The main properties you need when instantiating an atom are key
and default
, where the key
is a unique string that identifies an atom internally in Recoil and default
is the initial value of the state. You can create an atom without a default value, of course, just try not to. Read more...
Selector
“Selectors represent a function, or derived state in Recoil”, as it states in the official documentation. When you are creating the selector, you need to define the key
and get properties, where the key
is a unique string that identifies the selector internally and get
is a function that returns a value (it can be an async function as well). We explain that more later on. Read more...
Selector family
This function is used to read the state with help of a passed param. Basically, you can pass it an id and return only the part of the state based on that value. When you are creating the selectorFamily
you need to define the key
and get
properties, where the key
is a unique string that identifies the selector family internally in Recoil and get
is a function that accepts an argument which you passed into selectorFamily
, and it returns a function that is exactly the same as get
in the plain selector. You can use the sent value to search the state or do whatever you need to do. Read more...
useRecoilState(atom | selector)
A hook that returns a tuple of current atom, or selector, value and a setter function for that atom or selector, as built-in React’s useState
. Note that if you are calling this hook with a selector variable, it must be a writable selector - have set property defined. Read more...
useRecoilValue(atom | selector)
A hook that returns the current atom or selector value. This hook is intended to use when you only need to read the state, not write to it. Read more...
useSetRecoilState(atom | selector)
A hook that returns a setter function for a given atom or selector. Be aware that if you are using the selector must be writable to be able to use this hook. Also, this hook will not subscribe to the component to re-render when the value changes. Read more...
useResetRecoilState(atom)
A hook that will reset the state to the default value given when creating the atom. As the useSetRecoilState
, this hook will not subscribe the component to re-render when the value changes. Read more...
Starting with Recoil
1. Install it via package manager:
yarn add recoil or npm install recoil
2. Wrap your code in RecoilRoot component:
const YouAppCodeWrap = () => {
return (
<RecoilRoot>
<YourAppCode />
</RecoilRoot>
);
};
3. Create an atom:
const exampleAtom = atom({
key: "example",
default: false,
});
4. Use it:
const YourAppCode = () => {
const [exampleValue, setExampleValue] = useRecoilState(exampleAtom);
return <Button onClick={() => setExampleValue(!exampleValue)} active={exampleValue} />;
};
What's next? ⤵️
Switching code from redux to Recoil
Creating selectors
Creating selector families
But Recoil is missing something ...
Follow the article here
Thanks for reading this blog! My name is Bruno, and I work as a software engineer at Webiny. If you have any questions, comments, or just wanna say hi, feel free to reach out to me via Twitter.
Top comments (1)
dev.to/reactjs/redux-best-practice...