Watch on YouTubeThe player loads when you press play.

In this video

The first version of the drawing tool keeps every element in one React Context. Drag a single element and components that read the collection render again, even if their own element hasn’t changed.

I move the elements into an atom family so each one has its own state. Then I keep track of the active selection and edit its properties from another part of the interface. This is the same drawing tool I use in the two follow-up videos on asynchronous data and Suspense.

Get the drawing-tool code.

Read the automatic transcript

YouTube generated these captions and sometimes gets names, punctuation, and code wrong. Check the recording if something reads oddly.

0:00 — so I was recently asked why I like using recoils Atem family to store state in my apps and my answer was basically because it's a really great way to build very very well performing apps in react so let's dive into this a little bit deeper so I love using react context to manage my advise state over something like Redux or mob X its simplicity and lack of boilerplate to make it a great state management solution but the react context has one big limitation that can really hurt your apps performance and a new library called recoil can help with

0:30 — this so today I want to take a look at one of our equals most powerful features at some family so let's start by looking at the problem we have this prototyping tool and we have two rectangles on the canvas you can see performance is pretty good and we're only rearend during the items that need to change right so as I drag this Square over here only a tree renders and nothing else does and that's because each rectangle stores its state in its own component meaning if we change any of the properties of that element then only that element component will rerender but

1:00 — what if we wanted to add the sidebar that has access to this rectangle state well the only way to really accomplish this is to hoist the rectangle state's up into a common parent component but that means every time we change the state of one rectangle they would all rerender this is fine for most use cases but when you're dealing with a large number of frequently updating items then you have a problem and the limitation here is that you can't subscribe to just parts of the context that stores all of the items and we can't create a context for each item because we can't dynamically create contexts like this

1:31 — but recoil kind of gives you context on steroids we can store each item in its own piece of shareable state kind of like multi context and we'll only re-render what we need to making the performance of this app scale as we add more objects onto the canvas so let's take this slow app and supercharge it using recoil and you can clone this repo if you want to code along the link is in the description also if you have any questions please post them in the comments below and be sure to give me a like if you enjoyed this video and subscribe if you want to see more let's just quickly dive into

2:01 — what this app does I can click insert over here which will insert some rectangles with a random color I can then drag each rectangle around which will change its top and left positions and you can see the way this works is I have a left sidebar a canvas in the middle a right sidebar and then I have some global styles as well so what we do when we insert a new element is we push a new ID into this array of elements up here at the top and we make this array of IDs accessible to the canvas and inside of

2:32 — the canvas we just map over the element IDs just to render out each element and then each element stores its own top left and color State and this is actually really good because whenever we drag this element we're calling a set top and set left function within the element itself which will only update this component and not the whole app and this gives us great performance that scales as we add more elements but as we already saw the problem is if you want to take that state and share it with another component let's say with a sidebar which are going to be adding

3:03 — here we need to take the state and lift it up and that is well performance fulstone so now that we have a good idea for the basic layout of a app and where all the code lives let's dive right in so the first thing I'm gonna do is add recoil and now that we've added recoil we need to import recoil route from recoil and we're gonna wrap our app in this R equal read component I'm gonna head over to my element component and instead of storing our state in these separately State values over here I'm gonna store the

3:33 — state in what is called an atom family so let's import atom family from recoil and now we're going to create a new atom family just call it element state and we need to give the atom family a key so let's just call it element and a default value and our default value is just gonna be top:0 left:0 and the color is just gonna be a random material design color which we'll get using this handy library over here and now instead of these used States we're gonna remove that and import use recoil State instead

4:06 — from recoil and here we're going to bring in our user equal state hook pass in our atom family and to our atom family we will pass the ID of the element so let's bring in the ID as a prop so let's add it and now here I will get my element state and the ability to set my element you can see that this looks very similar to a you state but instead of setting some state that lives in this component specifically we're setting some state that lives outside of the component that

4:36 — can be shared so let's just pull in some values here so this is gonna be element dark top element left the color is going to be element but color and we're just gonna do the same over here but because we don't have separate state values for top and left here anymore I'm just gonna call set element instead spread in the current value of element and then our new top and left values and then we just need to change the usage of top and left over here as well all right and one last thing to do is head over to the canvas and pass this element ID in

5:07 — as a prop to the element because remember we need to use that to create a specific atom instance for that specific element okay great so we can still insert elements just one problem is that all the elements are being inserted with the same color and that's because this default object over here for our atom family only gets evaluated once meaning this random color and it gets generated once and is used as the default value for all new atoms so what we can do here is just wrap the default value in a

5:39 — function that returns this object meaning that every time we create a new atom this function is gonna run and return a new object each time for each new element and give us a unique random color for every element we insert okay great that's working brilliantly so we have the same functionality that we did when our state lived inside our element component so now we're in our right sidebar component which is going to be the component to the right of the app here which will have some values that we can change on this selected element so first we need a place to store the ID of

6:09 — the currently selected element so let's head back to our element component and import Adam from recoil so let's create an item called selected element ID state give it a key which will be selected element ID and the default value will be null but I just want to tell typescript that this can be either null or a number and now let's import use set recoil state from recoil and create a new variable here called set selected element and call use set or equal state

6:40 — and now we pass in our selected element ID state item and now on this container we're gonna add it on click and in the unclick we're gonna set the selected element to this current element ID now we can export this atom as well head back to our right sidebar and now we can import user equal value from recoil and we can also import from our element our selected element ID state and what we can do here is call our use recoil value

7:10 — hook part in our selected element ID state and let's just log it for now and then let's just add a label so that we know what we're looking at in the logs so you can see I have a few elements over here and whenever I click on one of the elements it's going to set the selected element value to the ID of that element this is great and all but we actually don't just want the element ID we need to be able to get and set the color of the element as well as the top and left values so we can use the selector for this so let's import selector from recoil and

7:42 — let's also import our element state so now let's create a new selector so let's say select an element state and make it a selector I'm gonna say the key is going to be selected element and we're gonna pass a get function to the selector and this gate function actually gives us another gate function so let's get the value of our selected element ID state which will give us the ID of the currently selected element so if our ID is not equal to null then we're going to return the value of our element state

8:14 — for this ID great so now instead of fetching our selected element ID over here let's instead pass in our selector to the ease recoil value hook so when we insert a new element and we select it you can see that we can now get the value of that specific element State so now we can remove our console.log and let's pass in the color value to our color picker and the top value to our top input and the left value to our left input and now you can see whenever I select an element the sidebar changes

8:45 — and we see the values for that specific element and as we drag that selected element around you can see that the values here change and this is great and here the best part if I highlight component updates using the reactive tools only the element that we change still updates we don't have that same problem of having potentially a hundreds of elements on the page and them all having to rerender just because we want to share state between the element and the sidebar but now we want to be able to sit our current element state as well

9:15 — well a selector actually allows you to set values so let's look at how that works so first we're gonna change our use recoil value hook to a use recoil static which is going to allow us to get both the value of that selector and a set function which will allow us to set the value of that selector so we need to implement a set function so let's add a set function and the set function actually gives us a set and a get function so first we need to know if the current ID of the selected element and

9:46 — now just to be safe we're still going to add in a check to make sure that there is actually an element that's selected and now what we can do is we can set our element state for that specific element and the set function is going to give us the new element value that we pass in to our set selected element so now what we can do is whenever the color picker value changes we can call a set selected element spread in the current value of that element but then pass in our new color value and we can do the same for

10:16 — top and the same for left so now what happens is our color picker value changes we call set selected element which will pass this new object to our selector which will get the current selected element ID make sure that we have one selected and then set that specific atom in that element state atom family to the new value that we passed in down here let's see this in action so I've inserted three elements here and if I select the orange one and change the color you can see that it changes and

10:47 — only this element story renders same with the top value and the left value and if I select this one same thing and this is one of the most common use cases of recoil where you have a large number of frequently updating items and it wouldn't make sense to store all of that state in one context value so I hope this gave you a good idea of how to use well when you need to store state for multiple items and when you might want to use this kind of technique thanks for watching thanks for making it all the way to the end and if you enjoyed this

11:17 — please give it a like and subscribe if you want to see more

Originally published on Jacques Blom.