DEV Community

Cover image for React with Typescript

React with Typescript

Mohammad Abdul Alim on October 19, 2021

At present react js has been a very popular library to build beautiful and scalable user interfaces. Today I would like to build a demo react proje...
Collapse
 
alim1496 profile image
Mohammad Abdul Alim

Thanks a lot for your valuable comment. I clearly understood the points of avoiding having object for state. Can you please explain why it is better to use ChangeEventHandler instead of ChangeEvent. Also I wanted to understand your comment regarding one way flow of data in this perspective.

 
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

 
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

Collapse
 
kylesureline profile image
Kyle Scheuerlein

Yeah, an object is probably not ideal for useState, but you can optimize it by passing a function. Instead of doing this...

setInput({...input, [name]: value})

...you can do this:

setInput((prevState) => ({...prevState, [name]: value}))

The key distinction is that with the first approach, handleChange really ought to be a useCallback with input as a dependency, but with the function approach it is not necessary.

I’m not sure that several useStates is better, actually. How about a useReducer instead?

Collapse
 
rammina profile image
Rammina

Thank you for sharing this! there were some things I didn't know of that you cleared up.

 
theluk profile image
Lukas Klinzing

You are right, but as I said, partly.

"Currently (React 16 and earlier), only updates inside React event handlers are batched by default” , according to Dan Abramov.

And

"React may batch multiple setState() calls into a single update for performance”, according to React’s documentation

So it is possible, that it is not batched.

 
joaolss profile image
João Lucas Silva • Edited

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

"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

Collapse
 
theluk profile image
Lukas Klinzing

I would disagree partly. Using set state for each field will cause rendering 5 times when you want to reset all fields at once. Also if you set one field, it will rerender the app the same amount of times as it would with setFields. Your other points sound a lot like just opinions because there is no specific reason in using a eventhandler type instead of a event type. If there are reasons for your suggestions, please let us know. Would like to hear your reasons behind this

 
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 =)

Collapse
 
konstagap profile image
konstagap

hi, Luke, could you explain why is it bad to have object as state and how having many usestate has less rerenderings than having all in one object?

 
alim1496 profile image
Mohammad Abdul Alim

nicely explained
thanks a lot

 
konstagap profile image
konstagap

Thanks you for explanation, I guess it's not gonna do any extra rerenderings in this particular case as we have all inputs in one component which still gonna render either way. thanks 👍

Thread Thread
 
joaolss profile image
João Lucas Silva

I'm also not a fan of having object as state, but your explanation for more rerenders does not apply, because if your state is an object but you are passing a variable inside this object which is a primitive then value equality applies for react to rerender or not, and if you are passing the entire object, the same would apply for creating the object inline with all the separate states inside it, it would be a new reference every render and would trigger rerender, so it only applies for nested objects, which no one should ever do because it is so much worse than a plain object inside one single state

Thread Thread
 
konstagap profile image
konstagap

Why do u think nested object is something that no one should ever do? I deal with forms and I have lots of nested objects that has arrays of objects and so on, I use one single object to keep all together in form, to update one field I just shallow copy old object, change field, pass new reference to setState and it works no problem, Is there another way how to do it?

Thread Thread
 
joaolss profile image
João Lucas Silva

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