DEV Community

Cover image for Discuss: React Hooks and Life After the Container-Component Pattern

Discuss: React Hooks and Life After the Container-Component Pattern

Jen Chan on November 15, 2019

I'm late to the party; I've been working with React for roughly 4 months and trying to build a project with Typescript and Redux. This past July, i...
Collapse
 
sabbin profile image
Sabin Pandelovitch • Edited

Hello Jen, I've recently did some refactoring on one of my apps to using hooks. I'll try to answer some of your questions. Take into consideration I don't use typeScript.

Have you switched over to hooks? Why or why not?

I have switched to hooks because I find the code to be more readable. Also to remove the higher order components and layers over layers which the Redux connect and withStyles from material-ui had over the previous version.

When I would open the debug for components I would always have the WithStyles Connect(where was the case) components over my components, it was kind of hard to. (I know there is a search I used...)

The useSlector and useDispatch hooks work like a charm without having to use a connect function. For the MaterialUI they have useStyles hook also

The life cycles are gone thanks for that also useEffect hook dose a pretty good job of you understand how to use it.

The only thing that I encountered an issue with is the shouldComponentUpdate implementation in hooks, I am still trying to get something to work in that matter...

Comparing the hooks and non hooks versions I can say that the hooks is more readable more lightweight and much easier to backtrace and debug.

How do you typically deal with updating a property of the state object that's nested several levels deep?

There are 2 scenarios here from my point:

  1. Component state
  2. App state - Redux in my case also

Component state:

Let's say you have a form with a state which you send a request or something. The form has some inputs and some other components, like an autocomplete which is a component also, with another component in it and so on. If the N level of component controls only the state of the form and nothing else in the app, then I pass the handlers down via props.

For the App state:

Take the example above and say that when we submit the form above we need to update the store. Then we dispatch and update action from the form in the onSubmit.

Following from the previous question: how do you manage shared state?

Actually the question for me was how do I manage the data flow between async API calls and multiple actions within the states.

For that I use redux-saga

The one thing I love about redux-saga is that I can control the actions, the outcome of async actions and actually have a precise control over the update of the store and dispatching actions.

To answer your case study. With the pizza shop. (Hope I understood correctly)

Assume that the above form, from the previous question, is a pizza order and on submit you have 2 states to update in the store User and Inventory. Update the user orders and remove one item from the inventory.

  1. onSubmit dispatch and action orderPizza(({ type: 'ORDER_PIZZA_REQUEST' , payload: formState}))

  2. A ReduxSaga would have a takeLatest effect on the ORDER_PIZZA_REQUEST which would have a generator function to handle the effects

  3. call an API to add the order.

  4. Assume we don't have an error from the API and we have an orderId from the response, we would use the put effect which actually dispatches an action, to dispatch 2 actions one INVETORY_REMOVE_ITEM with the pizzaId and one USER_UPDATE_ORDERS whit the orderId

  5. In the userReducer handle the USER_UPDATE_ORDERS and in the invetoryReducer handle the INVENTORY_REMOVE_ITEM

Collapse
 
jenc profile image
Jen Chan • Edited

Hi Sabin, thank you so much for your thorough response; I thought that my long rambling post totally lost and bored people. And yes you pulled the question out of my mouth:

" how do I manage the data flow between async API calls and multiple actions within the states?"

From component to app state, yes. I realize after re-reading your answer a few times, that my initial confusion was due to an assumption about architecture. I had not thought about async actions and was conflating data types with component state, thinking each data type required a state and a corresponding reducer, (i.e. UserState, ItemState for each pizza, InventoryState, OrderState), which is quite superfluous. That dogpiled into an assumption that in order for an action to update multiple states, (instead of async actions like you suggested), that reducers would receive multiple state types as params (Just imagine the state object being returned with mismatching and redundant info!)

I also realize I had not looked into how hooks are referred to in reducers; that should close the loop :D

This is all to say, thank you for walking me through the example with such clarity.

Collapse
 
arntj profile image
Arnt Joakim Wrålsen

I've started using React Hooks and find that they let you write better and cleaner code. The downside is that they are very different from the "traditional" approach in React and it takes some time to get your head around them. This can be an issue in a team where many devs are used to the "traditional" way of developing React components and don't really have the time or energy to re-learn everything they know about React.