Practical ways to use Recoil Atom and Atom Effects (with examples)
⚛️

Practical ways to use Recoil Atom and Atom Effects (with examples)

Date
Jun 22, 2022
Tags
React
Recoil

Pre-requisites:

  1. Familiarity with JavaScript
  1. Familiarity with React hooks - useState and useEffect

Atoms

Example 1:
 
Let’s say we have a color picker component and we want to change the color of the whole webpage, and the color picker component is in a completely different file, how can we do that?
This is something that can easily be done with recoil atom, check out the code below:
step 1: define the atom
export constselectedColorState= atom({ key: 'selectedColorState', default: '#ffffff', });
step 2:
Changing the value of the atom and using it:
We’re using SketchPicker from ‘react-color’: import { SketchPicker } from 'react-color';
 
const [backgroundColor, setBackgroundColor] = useRecoilState(selectedColorState);` `const handleChange = color => { console.log(color); setBackgroundColor(color.hex); }; return ( <div style={{ height: '100vh', backgroundColor: backgroundColor, display: 'flex', flexDirection: 'column', justifyContent: 'space-evenly', }} > <div style={{ fontWeight: '700', fontSize: '55px', textAlign: 'center', }} > Welcome back to Sansverse! </div> <div style={{ fontWeight: '700', fontSize: '20px', textAlign: 'center', }} > Choose background color: </div> <div style={{ position: 'fixed', top: '0px', right: '0px', bottom: '0px', left: '0px', }} /> <SketchPicker type="main" color={backgroundColor} onChange={handleChange} /> </div> ); };
 

Atom effects:

The following text is from Recoil official documentation

Compared to React Effects

Atom effects could mostly be implemented via React useEffect(). However, the set of atoms are created outside of a React context, and it can be difficult to manage effects from within React components, particularly for dynamically created atoms. They also cannot be used to initialize the initial atom value or be used with server-side rendering. Using atom effects also co-locates the effects with the atom definitions.
Example 2:
Suppose, I’m creating a web-app that allows a user to create different poster projects, something like this in Canva’s dashboard
notion image
To access a particular poster that is being stored in the storage, we need to have that project’s unique ID. Most websites have the unique ID as a random hash in the URL which may look like this:
My guess is that the UID of the project is: _GUKlHjngbJxCQNW1svn-A
We can use this UID to access and display the project we want to open using Atom Effects:
Note: This example is using Firebase version 8
const db = firebase.firestore(); const isBrowser = () => typeofwindow!== 'undefined'; export constSelectedProjectState = atom({ key: 'SelectedProjectState', default: { createdAt: newDate(0), name: '...', projectKey: 'unknown', }, effects: [ async ({ setSelf }) => { if (isBrowser()) { const location =window.location; const { search } = location; const currentSearch = newURLSearchParams(search); const workspaceKey = currentSearch.get('selectedProject') === null ? 'unknown' : currentSearch.get('selectedProject'); if (firebase.auth().currentUser !== null) { const uid = firebase.auth().currentUser.uid; if (workspaceKey !== 'unknown') { const newSelectedWorkspaceDoc = await db .collection('users') .doc(uid) .collection('projects') .doc(workspaceKey) .get(); const newSelectedWorkspace = newSelectedWorkspaceDoc.data() setSelf(newSelectedWorkspace); } else if (workspaceKey === 'unknown') { const newSelectedWorkspaceQuerySnapshot = await db .collection('users') .doc(uid) .collection('projects') .orderBy('createdAt') .limit(1) .get(); if (newSelectedWorkspaceQuerySnapshot.size > 0) { const newSelectedWorkspaceDoc = newSelectedWorkspaceQuerySnapshot.docs[0]; const newSelectedWorkspace = newSelectedWorkspaceDoc.data() setSelf(newSelectedWorkspace); } } } } }, ({ onSet }) => { onSet(newSelectedProject => { const { projectKey } = newSelectedProject; if (isBrowser()) { const location =window.location; const { search } = location; const currentSearch = newURLSearchParams(search); currentSearch.set('selectedProject', projectKey); const path = `/projects?${currentSearch}`; navigate(path, { replace: true }); } }); }, ], });
 
Hope this was a helpful article!
 
References: