Little React Things: Less reacting, more deriving
Tags: react, javascript, webdev
Published: 2023-01-17 14:51:33

---
series: Little React Things
title: Little React Things: Less reacting, more deriving
published: true
description: In this second post in the Little React Things series, I talk about how we should remove unnecessary reactions from our React applications and replace them with derivations.
tags: react, javascript, webdev
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b71wjbz3iqkcncxc27ig.png
# Use a ratio of 100:42 for best results.
canonical_url: https://www.zekehernandez.com/posts/little-react-things-less-reacting-more-deriving
---
*Little React Things is a series of short, React-focused posts where I share some things I've learned over the past few years of developing with React. I hope you find them helpful. These posts might be most helpful for those who have at least a little experience with React already.*

Back when React Hooks first came out, the `useEffect` was introduced and many like myself were like "great, a utility to react to things changing and keeping things in sync". And that is partially true, but it's not as simple as that. The new React docs that are under construction are more explicit about how and how not to use `useEffect` in the [You Might Not Need an Effect](https://beta.reactjs.org/learn/escape-hatches#you-might-not-need-an-effect). 

Even with the guidance from the new docs, these `useEffect`s still tend to pop up in the wild. They can be more than just unnecessary, and actually problems that should be fixed.

## A hasty reaction
Let's say we have an app where a user can buy clothes, but instead of picking out each individual article of clothing, they can pick a bunch of articles of clothing that they like and set a price. Then the application shows the user a bunch of outfits that fit the chosen parameters.

The parent component of the app is where the user can pick the different pieces of clothing from the main list. Then there is a child component, `OutfitList` that lists all the outfits that fit the parameters.  This list of outfits is generated by a very cool helper function called `createOutfits`; it's not an outrageously expensive function, but we definitely don't want to call it each time the `OutfitList` is rendered (this kind of function would not be done in the browser typically, but this is a React post, so here we are).

Let's take a look at a way we could create this `OutfitList` component.
```jsx
function OutfitList({ clothingItems, maxPrice }) {
	const [outfits, setOutfits] = useState(null)

	useEffect(() => {
		const createdOutfits = createOutfits(clothingItems, maxPrice)
		setOutfits(createdOutfits)
	}, [clothingItems, maxPrice])

	return (
		<div>
			{outfits ? outfits.map(outfit => (
				<Outfit key={outfit.id} outfit={outfit} />
			)) : null}
		</div>
	)
}
```

It's great right? We have a `useEffect` set up to react to changes in the clothing item list or price limit and recreates the list of outfits and updates the `outfits` state. We only call the `createOutfits` function when we need to and we keep `outfits` in sync. All good? Well, there are a couple of issues with this solution. 

### Reactions are usually not a good idea
Hold up, but it's called "React", what do you mean reactions aren't a good idea? Well, the reacting that we do want is reacting to user actions primarily and also asynchronous events. Code that synchronously reacts to your own code, on the other hand, is not desirable.

When the `OutfitList` first renders, even if `clothingItems` is already populated `outfits` will still be `null`. This is because `useEffect` runs after the render. So, for the first render we have populated `clothingItems` and `null` `outfits`. The state is out of sync for that first render which is no good. Our components then need to be made in such a way to account for these discrepancies. For example, we need to add a check to see if `outfits` is `null` as shown in the code above.

Furthermore, in the last post, I gave the guidance to not call the [function that is a React application]() more than you need to, and here the `useEffect` is calling that function immediately after it is first called. So instead of one render, we will always have at least two renders each time either `outfits` or `maxPrice` changes.

### State should be the source of truth
For our `OutfitList` component, let's assume that `clothingItems` and `maxPrice` are state in the parent component. Given that, we have three states: `clothingItems`, `maxPrice` and `outfits`. But are those three states actually representing different things? I would argue no. `outfits` is just a derivation of `clothingItems` and `maxPrice`.

This isn't good, state should be a source of truth. But here we have `clothingItems`, `maxPrice`, and `outfits` as state, so which is the source of truth? From the user's perspective, I would probably say it's `clothingItems` and `maxPrice`.

Why is this important? Well, what if down the road a developer is going to add a feature where the user can add a new outfit to the outfit list. The correct way to do this would be suggest some outfits that include a piece that weren't in the `clothingItems` list or that was a slightly higher price than `maxPrice` and then if the user picks one of those outfits, adjust those states accordingly. But this developer could see some state called `outfits` and simply just append a new outfit to that list. Uh oh, now we're really out of sync. We have a list of outfits that could *not* be created from our set of `clothingItems` or that is a higher price than the price limit. This example is a little contrived, but I hope you get the point at least.

## Deriving forward
```jsx
function OutfitList({ clothingItems, maxPrice }) {
	const outfits = useMemo(() => {
		return createOutfits(clothingItems, maxPrice)
	}, [clothingItems, maxPrice])
	
	return (
        <div>
			{outfits.map(outfit => (
				<Outfit key={outfit.id} outfit={outfit} />
			)}
		</div>
	)
}
```

Here we are being explicit that `outfits` are derived from `clothingItems` and `maxPrice`. On the first render, `outfits` will have a value (given that `clothingItems` and `maxPrice` have values of course), we aren't immediately re-rendering after the first render, and we are still only calling `createOutfits` when `clothingItems` or `maxPrice` changes thanks to `useMemo`.

So there you have it, with one technique we followed all three guidelines from the last post, we reduced the number of function calls (renders), simplified the parameters (state), and used memoization. Until next time!