DEV Community

Discussion on: React with Typescript

joaolss profile image
João Lucas Silva

useReducer would be much better to deal with nested objects inside a state

Thread Thread
lukeshiru profile image
LUKESHIRU • Edited on

The explanation is more for nested stuff, but yeah, too much to explain in a single comment, but enough for other folks to google it. The reason of not having to do a copy of the object every time should be compelling enough.

Edit: I answered from the notifications and for some reason the answer ended up here, but it was for the comment about "this doesn't apply to plain objects".

Thread Thread
joaolss profile image
João Lucas Silva

Just that you did the explanation using primitives, it would be good to mention the problem is nested objects bc of reference equality, sorry if im being cranky, but i feel it is hard enough for beginners to grasp the reference equality thing on js, it is always good to emphasize this when it comes up

Thread Thread
lukeshiru profile image
LUKESHIRU

I generally prefer to just say "never do this bad practice" instead of, "don't do it in this 9 of 10 scenarios, and in that 1 scenario that you can, be careful". My point is that we shouldn't default to objects as state, and we should try to have one state per value, which also encourages you to avoid having lots of state in a component.

Thread Thread
joaolss profile image
João Lucas Silva

I'm not a fan of dos and don'ts that dont explain why this should be the case, it encourages people to be the "ctrl-c ctrl-v of stackoverflow" kind of dev, instead of creating a deeper understanding of the language and the framework

Thread Thread
lukeshiru profile image
LUKESHIRU

I mean, if folks can't google by themselves and need every single thing to be explained in a comment, how will they improve as devs over time? I can go over why something is a bad practice in a comment or I can just mention is a bad practice and let them google it themselves, (or even let them ask and generate a deeper discussion as it happened today 😅). If somebody is expecting to have everything served on a silver plate, learning new things will be harder and harder over time 🙁

Thread Thread
konstagap profile image
konstagap

'useReducer would be much better to deal with nested objects inside a state'

-what is the benefit of that? writing more code? setup reducer and dispatch actions when u still keep state as an object and can just copy an object and use same setState function. Same performance too. But much better.

The reason of not having to do a copy of the object every time should be compelling enough.

  • I dont understand what is wrong with making copy of object? u try save memory? u try save what?
    So when calling useState u create a state var and a method setState:
    const [state.setState] =useState('');
    when u put each value in your own useState u create a bunch of independent setState methods takes space, which can be replaced with one setState if initial state was an object. compelling enough?)))
    Lets say u have 30 fields? what a noise in code, what a waste)))

  • If somebody is expecting to have everything served on a silver plate, learning new things will be harder and harder over time 🙁

Brother, learning will be harder overtime no matter what, that is why we are here, to help and explain. dont be like that, just be good and bring to the table =)

Thread Thread
lukeshiru profile image
LUKESHIRU

If you have a state with 30 fields (either as props of an object or as separate states), tbh the problem is elsewhere.

And when I said that not having to do a copy of the object should be enough of a reason to not do it this way, it wasn't because of performance (even if performance would be worse in normal scenarios), but more about avoiding the boilerplate every time we update the state.
I mean, the old this.setState did that copy for us, but the useState hook doesn't because it wasn't designed to be used like that.

Thread Thread
joaolss profile image
João Lucas Silva • Edited on

Because you avoid shooting youself on the foot and wrongly mutating the state object, you can use immer to immutability, and you can deal with more complex trabsformation in the reducer, and in last case you can write I reducer simple enough that it just contains the code that you would have to write inside setState to mutate a variable inside the object, so you dont have to write it in each setState (or useCallback just to do that) instead you can do this logic in the reducer and use the dispatch as the setState, so yes it is definitely better to use the useReducer hook and there is no benefit at all in using useState for objects

Edit: putting a example so you can see what im talking about:

const reducer = (state, action) => ({ ...state, ...action })
...
const [state,setState] = useReducer(reducer, { a: 1, b: 2})
...
setState({ a: 3 })
// new state: { a: 3, b: 2 }
Enter fullscreen mode Exit fullscreen mode

same amount of code, safer/cleaner code

Thread Thread
konstagap profile image
konstagap • Edited on

"Because you avoid shooting yourself on the foot and wrongly mutating the state object" - how is your example prevents that? u not dispatching anything, u basically using useReducer as a useState. Anyways, it's good if it works for you, I don't know how come it is safer/cleaner than this
const [state,setState] = useState({ a: 1, b: 2});
setState(prev =>({...prev, a:3 });
Notice how it does the same thing without writing a reducer?
BTW you using the reducer wrong. To use useReducer right, to "avoid shooting yourself on the foot" refer to docs reactjs.org/docs/hooks-reference.h... .
I know you have seen them, but maybe take a second look so you can see what I'm talking about.

Thread Thread
joaolss profile image
João Lucas Silva

it is safer because you dont need to remember to spread the old object everytime you need to update the state, it is cleaner because you are only spreading an object on the reducer, and you don’t have to rely on other devs doing it. “You not dispatching anything” you clearly don’t know the difference between reducer and flux paradigm, they are connected but are not the same, the documentation states: “ useReducer is usually preferable to useState when you have complex state logic that involves multiple sub-values” in verbatim, tell me where in there it shows that im wrong