DEV Community

Discussion on: Using React useState Hook to Manage Object Props

Collapse
 
brense profile image
Rense Bakker

You can also use a reducer function for this, so you dont have to spread the current state manually for each setPlayer call:

const initialState = {
  name: 'Player',
  score: 0,
  level: 1,
  weapon: 'Bow',
  arrows: 20,
}

function playerReducer(currentState: typeof initialState, nextState: Partial<typeof initialState>){
  return { ...currentState, ...nextState }
}

function Player(props: Partial<typeof initialState>){
  const combinedInitialState = useMemo(() => ({ ...initialState, ...props }), [props])
  const [player, setPlayer] = useReducer(playerReducer, combinedInitialState)

  const handleShootArrow = useCallback(() => {
    setPlayer({
      // we dont have to spread the whole player object here
      // because the reducer already does that for us
      arrows: player.arrows - 1,
      score: player.score + 10
    })
  }, [player])

  // ...
}
Enter fullscreen mode Exit fullscreen mode

You could also make the reducer more complex, for example you could do something like this:

function playerReducer(currentState: typeof initialState, action: { type: 'SHOOT_ARROW' }){
  switch(action.type){
    case 'SHOOT_ARROW':
      return {
        ...currentState,
        arrows: currentState.arrows - 1,
        score: currentState.score + 10
      }
  }
}
Enter fullscreen mode Exit fullscreen mode