Nick09
Nick09

Reputation: 228

Managing multiple states inside hook

I've recently started to try to learn React hooks, but for the life of me I can't figure out some things, like multiple state management, I've found a few example but nothing seems to be in a specific pattern. I'm not even sure how you're supposed to define your states if there's more than 2 and you want to change them individually, should it be like this:

const [slides, setSlides] = useState([])
const [currentSlide, setCurrentSlide] = useState(0)
const [tagName, setTagName] = useState([])

Or like this:

const [states, setStates] = useState({
  slides: [],
  currentSlide: 0,
  tagName: []
})

And if both or the second one is viable (honestly I would prefer the second one since its less repetitive in calling useState and closer to the standard state meta) how could one go about changing states in such a example? I couldn't really find anything on this, so what I tried was this:

useEffect(() => {
  Object.entries(Slides).forEach(slide => {
   setStates(prevState => ({ slides: [...prevState.slides, slide[1]] }))
  })

}, [])

And I messed around with it a bunch trying to get some decent results but I couldn't get it to work properly.

Any ideas of what I'm doing wrong? And on which one of these to methods of best practice?

Thanks!

Upvotes: 1

Views: 483

Answers (2)

Mayank Shukla
Mayank Shukla

Reputation: 104379

In terms of updating state, first template is much easy and simple, because each stateUpdate function will be responsible for updating single value, that can be obj/array/int/bool/string. Another thing is, to access each value of the state (it will be an object), you need to write states.slides, states.tagName etc.

With first case, state update will be simply:

// only value in case of int/string/bool
updateState({ [key]: value }) or updateState(value);

But in second case, state will be an object with multiple keys, so to update any single value you need to copy the object, then pass the updated key-value. Like this:

updateState({
  ...obj,
  [key]: newValue
})

To update the slides array:

updateState(prevState => ({
  ...prevState,
  slides: newArray
}))

Handling complex state update:

Use useReducer to handle the complex state update, write a separate reducer function with action types and for each action type so the calculation and return the new state.

For Example:

const initialState = { slides: [], tagName: [], currentSlide: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'SLIDES':
      return { ... };
    case 'TAGNAME':
      return { ... };
    case 'CURRENT_SLIDE':
      return { ... }
    default:
      throw new Error();
  }
}

function Counter({initialState}) {
  const [state, dispatch] = useReducer(reducer, initialState);
  ....
}

Upvotes: 1

Arnaud Christ
Arnaud Christ

Reputation: 3551

It is true that the useState hook can become quite verbose when dealing with complex state object. In this case, you can also consider using the useReducer hook.

I would recommend the reading of this article about useState vs useReducer.

Upvotes: 1

Related Questions