Do you ever find yourself in React useState hook hell?
Yeah, this good stuff:
import { useState } from "react";
function EditCalendarEvent() {...
For further actions, you may consider blocking this person and/or reporting abuse
This post literally changed my life
It's bad designed anyway. This
EditCalendarEvent
component, have a lot of responsibility. Having 6 input fields, you will re-render everything every time you change any of that fields because you share state anduseEffect
oruseReducer
doesn't matter here.Rerender is ignored for the other 5 fields if their values didnt change, the props will be the same and it will keep the DOM elements that are already there for those fields.
How would you suggest to make a component to edit some data model, like a calendar event, that has multiple fields (e.g. name, date, description, etc.)? It's a pretty common case to have modals like these with multiple input fields and the solution suggested by the author is pretty good imho.
EditCalendarEvent
components holds global state as single states withuseState
or as single object withuseReducer
, so it will re render whole component on each change. WithuseReducer
new object is returned so it have same component update behaviour as using multipleuseState
. Only one change is here that you have validation logic in one place.You can create separate components for inputs that will hold own state or use refs instead of state for that data.
A lot of form don't require that anyway, you can just get form data in
onSubmit
callback like so:useReducer
is nice for things that changes together, form independent input fields in form, not so much.I dont think you can consider the event data as global state, its bound to the specific form component. You have to consider the case here that you are fetching the event data from a database (when editing for example). You are not going to do individual database queries for each field, so you need some way to pass down the event data to the individual input components.
There is no issue with this aslong as you keep the values referentially equal, so React is able to determine that the props/state for the other inputs didnt actually change. If React can determine that the props/state did not change, it will not make any DOM changes for those components.
The example by the author with the useReducer hook, is a good/clean way to achieve this.
Yes, I mean "global data" in context of this specific components tree.
Great share! However, you can also achieve the same behavior with
useState
using a curried function ( also with the ability to supply a function that controls state transitions ):I've done this before but slightly different
Just to be sure I get the most up-to-date state
I also do in this way. Just adding a point, instead of
setEvent(event => ({ ...event, [prop]: e.target.value }));
do
setEvent(prevEvent => ({ ...prevEvent, [prop]: e.target.value }));
It's not much of a difference but you would have a better code readability.
— A cure for React useState hell?
— Angular!
😅
If seriously, great post, thank you 👍
How so? Serious question here. I've been away from Angular for some time, I'd be really pleased to know how Angular deals with this nowadays.
Until now, I have always avoided useReducer, but after your explanation, I won't anymore. Thank you:)
I believe some excellent points have been made in this post. I particularly like the section where you discuss your thoughts on cases where using useState or useReducer, leaves a lot to be considered!
Great and clear explanation!
You are so true, each and every piece of example found online implies the switch part, making it somehow more difficult to understand the whole pattern.
This, combined with React context is for some time now, my everyday state-management solution. Simple and clear!
Thank you for clearing things up a little for everyone!
Greetings from Romania!
PS: this article should be in the official react.js documentation :)
I never thought of using dispatch function to carry updated state values instead of actions - this is really cool!
Great post, thank you 👍
This is what happens, when we are not limited in our mind for thinking, experimenting and exploring possiblilities to simplify things.
Awesome post.
Great in-depth review of using
useReducer
. It's often avoided by the developers but after understaning how to use it - it solves many issues!🤜🤛🤓
Mobx + dependency injection handles those perfectly.
Great article on looks at the pros and cons.
useState
can access the previous state as well. When used asprev => ...prev
over...state
, you get the same benefits. A large section of this article's benefits ofuseReducer
just for the previous state can be negated as a result of the same functionality inuseState
.I think the trade-off isn't that good. First you add a lot of code complexity the cognitive load needed to read your code is too great. Second if you have a "useState hell" that usually means your component is too big and you should break it into smaller forms/components.
It also depends a lot on the use case.
In the case of a form for example, I would prefer delegating all the validation and state management to react-hook-form + yup, much more cleaner, you don't need any state at all..
Imho, if you find your component has a big state and you're looking for solutions how to manage this big state:
-- you should instead divide your component into smaller components.
I believe that's the essence of React and of component based programming.
:)
Arguably in most cases a component should have just a single line of useState.
in other words components & api context
in my opinion use zustand.
Call me the enemy of the state, but I will always use classes over anything.
That is because you know the power of classes ;). In the world of JS it is rare enough thing.
Everyone was so into "hating classes" until hooks came out and everyone was soo into it :) and some time later we have an ocean of articles with the titles that go like "useState hell", "useEffect is so dangerous" and so on and so forth.
If I recall correctly there was only one issue with the classes: they were uhmmm, "awkward" to many JS developers. Oh and that weird "this" behaviour that would bite everyone at least once ;).
Well, hooks look like a fair trade of :)
🤜🤛 🤓
Junior dev me would love this, experienced dev me 🫣 nope nope nope. Obscuring code for the sake of brevity, bad bad bad.