2.13 Reducer统一的状态管理集合

一、Reducer

  1. 对于拥有许多状态更新逻辑的组件来说,过于分散的时间处理程序可能会令人不知所措。对于这种情况,你可以将组建的所有状态更新逻辑整合到一个外部函数中,这个函数叫做reducer

  2. Reducer是处理状态的另一种方式

  3. 原代码样式

    import { useState } from 'react'
    
    function App() {
      const [list, setList] = useState([
        { id: 1, text: '111' },
        { id: 2, text: '222' },
        { id: 3, text: '333' },
      ])
    
      const handleAdd = () => {
        setList([...list, { id: 4, text: '444' }])
      }
    
      const handleEdit = (id) => {
        setList(
          list.map((item) => {
            if (item.id === id) {
              return { ...item, text: 'new' + item.text }
            } else {
              return item
            }
          })
        )
      }
    
      const handleRemove = (id) => {
        setList(
          list.filter((item) => {
            if (item.id === id) {
              return false
            } else {
              return true
            }
          })
        )
      }
    
      return (
        <>
          <div>Default Template</div>
          <input type="text" />
          <button onClick={() => handleAdd()}>添加</button>
          <ul>
            {list.map((item) => {
              return (
                <li key={item.id}>
                  {item.text}
                  <button onClick={() => handleEdit(item.id)}>编辑</button>
                  <button onClick={() => handleRemove(item.id)}>删除</button>
                </li>
              )
            })}
          </ul>
        </>
      )
    }
    
    export default App
    
  4. 通过Reducer后

    import { useReducer } from 'react'
    
    // 由这个Reducer函数完成外部逻辑的统一处理
    // state表示内容,action表示具体操作的参数
    function listReducer(state, action) {
      switch (action.type) {
        case 'add':
          return [...state, { id: 4, text: '444' }]
        case 'edit':
          return state.map((item) => {
            if (item.id === action.id) {
              return { ...item, text: 'new' + item.text }
            } else {
              return item
            }
          })
        case 'remove':
          return state.filter((item) => {
            if (item.id === action.id) {
              return false
            } else {
              return true
            }
          })
      }
    }
    
    function App() {
      const [list, dispatch] = useReducer(listReducer, [
        { id: 1, text: '111' },
        { id: 2, text: '222' },
        { id: 3, text: '333' },
      ])
    
      return (
        <>
          <div>Default Template</div>
          <input type="text" />
          <button onClick={() => dispatch({ type: 'add' })}>添加</button>
          <ul>
            {list.map((item) => {
              return (
                <li key={item.id}>
                  {item.text}
                  <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
                    编辑
                  </button>
                  <button onClick={() => dispatch({ type: 'remove', id: item.id })}>
                    删除
                  </button>
                </li>
              )
            })}
          </ul>
        </>
      )
    }
    
    export default App
    
  5. immer版本:

    import { useImmerReducer } from 'use-immer'
    
    // 由这个Reducer函数完成外部逻辑的统一处理
    // state表示内容,action表示具体操作的参数
    function listReducer(draft, action) {
      switch (action.type) {
        case 'add':
          draft.push({ id: 4, text: '444' })
          break
        case 'edit':
          // ESlint校验失败,不知道为啥
          const value = draft.find((item) => item.id === action.id)
          value.text = 'new' + value.text
          break
        case 'remove':
          // ESlint校验失败,不知道为啥
          const index = draft.findIndex((item) => item.id === action.id)
          draft.splice(index, 1)
          break
      }
    }
    
    function App() {
      const [list, dispatch] = useImmerReducer(listReducer, [
        { id: 1, text: '111' },
        { id: 2, text: '222' },
        { id: 3, text: '333' },
      ])
    
      return (
        <>
          <div>Default Template</div>
          <input type="text" />
          <button onClick={() => dispatch({ type: 'add' })}>添加</button>
          <ul>
            {list.map((item) => {
              return (
                <li key={item.id}>
                  {item.text}
                  <button onClick={() => dispatch({ type: 'edit', id: item.id })}>
                    编辑
                  </button>
                  <button onClick={() => dispatch({ type: 'remove', id: item.id })}>
                    删除
                  </button>
                </li>
              )
            })}
          </ul>
        </>
      )
    }
    
    export default App
    

最后更新于