Derive and Conquer: How to get rid of useless useState

·

2 min read

I have seen this anti-pattern being used in so many React code bases

We have some values and we need to process them somehow to show a derived value.

In a lot of codebases you would see people do this:

const [fullName, setFullName] = useState("");

useEffect(() => {
  setFullName(firstName + lastName)
}, [])


return <p>{fullName}</p>

This is a known anti pattern and there are lots of blogs about it out there.

What happens is that React first renders this with an empty fullName and then immediately renders it again as soon as the useEffect has run and the fullName is updated.

We can bypass all of this by setting derived values directly, since they will get updated whenever the props change, we can just do:


const fullName = firstName + lastName

return <p>{fullName}</p>

The fullName is set before the first render and it will update it whenever the props change.

A similar example would be with Arrays.

Suppose you have an array with Todos where you need to filter out tasks that are done

Instead of doing

const [doneTodos, setDoneTodos] = useState([]);

useEffect(() => {
  setDoneTodos(todos.filter(todo => todo.done))
}, [todos])


// render doneTodos

Do this and save a render


const doneTodos = todos.filter(todo => todo.done)

// render doneTodos

Not only is this much more optimized, you also don't have to deal with out-of-sync issues with Todos Array and doneTodos since it is being set inside a useEffect in the earlier example and if you forget to update it properly it will go out of sync.

Remember to use useState when you need it. If a value is internal and needs to maintained and changed inside it, you should use useState.

If it's passed down from other components, you don't need to store it inside the child component.