[React] When to useReducer instead of useState

Posted answer1215

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[React] When to useReducer instead of useState相关的知识,希望对你有一定的参考价值。

useState is typically simpler at first than useReducer (you can even implement useState using useReducer), but there‘s one scenario where useReducer is almost certainly better than useState:

When one element of your state relies on the value of another element of your state in order to update: useReducer

More information: KcD‘s blog

 

import React from ‘react‘
import ReactDOM from ‘react-dom‘

function undoReducer(state, action) {
  const {past, present, future} = state
  const {type, newPresent} = action

  switch (type) {
    case ‘UNDO‘: {
      if (past.length === 0) return state

      const previous = past[past.length - 1]
      const newPast = past.slice(0, past.length - 1)
      return {
        past: newPast,
        present: previous,
        future: [present, ...future],
      }
    }
    case ‘REDO‘: {
      if (future.length === 0) return state
      const next = future[0]
      const newFuture = future.slice(1)
      return {
        past: [...past, present],
        present: next,
        future: newFuture,
      }
    }
    case ‘SET‘: {
      if (newPresent === present) {
        return state
      }
      return {
        past: [...past, present],
        present: newPresent,
        future: [],
      }
    }
    case ‘RESET‘: {
      return {
        past: [],
        present: newPresent,
        future: [],
      }
    }
    default: {
      throw new Error(`Unhandled action type: ${type}`)
    }
  }
}

function useUndo(initialPresent) {
  const [state, dispatch] = React.useReducer(undoReducer, {
    past: [],
    present: initialPresent,
    future: [],
  })

  const canUndo = state.past.length !== 0
  const canRedo = state.future.length !== 0

  const undo = React.useCallback(() => {
    dispatch({type: ‘UNDO‘})
  }, [])

  const redo = React.useCallback(() => {
    dispatch({type: ‘REDO‘})
  }, [])

  const set = React.useCallback(newPresent => {
    dispatch({type: ‘SET‘, newPresent})
  }, [])

  const reset = React.useCallback(newPresent => {
    dispatch({type: ‘RESET‘, newPresent})
  }, [])

  return [state, {set, reset, undo, redo, canUndo, canRedo}]
}

function App() {
  const [state, {set}] = useUndo(‘first‘)

  React.useEffect(() => {
    set(‘second‘)
  }, [set])

  React.useEffect(() => {
    set(‘third‘)
  }, [set])

  return <pre>{JSON.stringify(state, null, 2)}</pre>
}

ReactDOM.render(<App />, document.getElementById(‘root‘))

 

以上是关于[React] When to useReducer instead of useState的主要内容,如果未能解决你的问题,请参考以下文章

在 React 中使用 useReducer 钩子过滤列表?

[react] 请说说什么是useReducer?

React中useReducer的理解与使用

React中useReducer的理解与使用

React useReducer 异步数据获取

使用带有 useReducer() 钩子的 React Context API 有啥优点和缺点?