Search code examples
reactjsreact-hooksreact-state-management

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!


Solution

  • 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);
      ....
    }