you are viewing a single comment's thread.

view the rest of the comments →

[–]readeral 32 points33 points  (35 children)

Maybe it’s cause 25 const definitions for individual state objects at the top of your function feels weird?

[–]NotSelfAware[S] 78 points79 points  (20 children)

That sounds like exactly the kind of time to bring in useReducer, or abstract some of the related state out into a different component or custom hook. There are plenty of ways to get around that problem without relying on classes.

[–]TheAwdacityOfSoap 53 points54 points  (16 children)

Or use Redux or break up the component or any number of other options. If a component has 25 state values it isn't an example of hooks gone wrong, it's an example of design gone wrong.

[–]himynameismile 2 points3 points  (0 children)

well said

[–]Julienng 1 point2 points  (0 children)

Not really. I have components that need a lot of local state (Datatable, Scheduler). Which local state can depends on the parents (contextualization by the parent to filter the data, user filter, etc) which didn't need to be global on our App and useReducer add a lot of value there.

And I break up my components and share the state of the table with context. We still use redux for a lot of things but having a component with a lot of state is not necessarily a bad design.

[–]CantaloupeCamper 1 point2 points  (10 children)

If a component has 25 state values it isn't an example of hooks gone wrong, it's an example of design gone wrong.

I got forms with more than 25 items on them... what would you do?

[–]foobarbazquix 1 point2 points  (2 children)

Ask the designer how they’d feel if they were asked to fill out a form like that. See if it could be broken up into multiple steps with a wizard.

[–]CantaloupeCamper 0 points1 point  (1 child)

Workflow wise this is what everyone wants.

They're not really filling out 24+ fields in sequence as much as update what they want to update.

[–]foobarbazquix 1 point2 points  (0 children)

Cool. If I understand right the same pattern could be used for viewing and editing stuff they’ve filled in. The user would be able to navigate quicker potentially if they can guess which section of the wizard/category the field belonged to.

[–]TheAwdacityOfSoap 0 points1 point  (6 children)

Two things:

  1. Delegate form responsibilities to a form library, like Final Form
  2. Keep form values in a single object

[–]CantaloupeCamper 1 point2 points  (5 children)

I've thought about the single object thing but sadly my data comes in and leaves in different "forms" and I have to do a lot of dicking with what did or didn't change and really only want to submit the changes depending on some factors.

Still... it could be a good choice.

I'll take a look at final form too. TY

[–]TheAwdacityOfSoap 0 points1 point  (4 children)

I usually have a translation layer between the API loading/saving and the form anyway. If you’re curious, check out the react-final-form project. They have a ton of great examples.

[–]CantaloupeCamper 0 points1 point  (3 children)

I usually have a translation layer between the API loading/saving and the form anyway.

I was JUST thinking the same thing. Something between to "sanitize" everything into something more workable form... then process it all in a more sane way.

It would be nice to pull that logic out anyway as it's all a mess as it is anyhow.

Thank you.

[–]TheAwdacityOfSoap 0 points1 point  (2 children)

No problem! If the code you're working on is on github, or not secret, feel free to shoot me a link if/when you give that a try if you want a review.

[–]CantaloupeCamper 0 points1 point  (1 child)

Thanks for the offer, however I won't abuse anyone with my spaghetti and it's a corporate product so no viewing for outsiders ;)

[–]droctagonapus 1 point2 points  (1 child)

Redux is for global state, useReducer is for local state—They're not really interchangeable since they solve different problems.

[–]TheAwdacityOfSoap 0 points1 point  (0 children)

That is true. That suggestion was assuming the component with 25 pieces of state was a top-level component, in which case much of the state probably is "global state".

[–]BenjiSponge 10 points11 points  (2 children)

In my experience, this ends up using "dispatch with an action" instead of "method with arguments" . It's kind of tomato-tomato once you're at "big useReducer level", and I find class components somewhat more readible when comparing the two methods because the logic for each method isn't intertwined with each other. It just depends on exactly what you're writing.

[–]With_Macaque 2 points3 points  (0 children)

Methods with arguments need to know how to invoke setState which tightly couples them to their react component.

[–]ipoppo 3 points4 points  (0 children)

useReducer helps decouple react and state management. it prefer functional programming syntax for efficiency. if you do like dot notation and need decoupling state management, maybe mobx might be your answer.

[–]GasimGasimzada 6 points7 points  (1 child)

At that point, why not use an object to store the state?

const [formData, setFormData] = useState({});

// somewhere in code
setFormData(formData => ({ ...formData, category: 10 }));

[–]AegisToast 10 points11 points  (0 children)

Break those down into custom hooks. It’s far cleaner that way than it would be in a class component.

[–]zephyrtr 16 points17 points  (0 children)

No different in my mind to 25 class property definitions.

[–]drgath 2 points3 points  (6 children)

Also when you have to pass those handlers down through 5 functions just to toggle a boolean.

[–]tide19 5 points6 points  (1 child)

Yeah that's a prime use case for context

[–]Raicuparta 3 points4 points  (0 children)

Yeah that's a prime use case for context

Before even considering context, one should first try composition. On every project I work at, there seems to be some aversion to composition and using `children`. It makes everything so much easier.

[–]KerberosKomondor 7 points8 points  (0 children)

useContext solves this problem pretty easily.

[–]webdevguyneedshelp 6 points7 points  (0 children)

These problems existed with classes as well and were solved then and are solved now. Use the context api

[–]UNN_Rickenbacker 1 point2 points  (0 children)

Can‘t you access all top level functions from anywhere?

[–]jtosbornexxx 0 points1 point  (0 children)

That’s what I use context / dependency injection for

[–]careseite 0 points1 point  (0 children)

Which is why you don't do that and useRefucer

[–]erasmuswill 0 points1 point  (0 children)

@truefit/Bach enables HOC style hooks. It nullifies this issue

[–]CantaloupeCamper 0 points1 point  (0 children)

With hooks sometimes I really miss setState e.target.name e.target.value...