React-useReducer

useReducer

usesSate 只有 setState 一个方法修改 state,useReducer 相当于能自定义多个修改 state 的方法。useReducer 是一个 React Hook,它允许你向组件里面添加一个 reducer。

使用方式

const [state, dispatch] = useReducer(reducer, initialArg, init?)

传入的参数是

  • 用于更新 state 的纯函数 reducer 。reducer接受两个参数—— state 和 action 。返回值是更新后的 state 。
  • initialArg 是初始化 state 的任意值。如果第三个参数 init 存在,则根据 init 的逻辑计算初始值;否则,直接使用 initialArg 作为初始值。
  • 可选参数 init 是用于计算初始值的函数,接受 initialArg 作为参数,返回值为 state 的初始值。

返回值有两个

  • 当前的状态 state ;
  • dispatch 函数,用于更新 state 并触发组件的重新渲染;

注意事项:

  • useReducer 是一个 Hook,所以只能在 组件的顶层作用域 或自定义 Hook 中调用,而不能在循环或条件语句中调用。

Reducer

Reducer 函数可以将组件所有状态更新逻辑整合到一个外部函数当中。可以通过三个步骤将 useState 迁移到 useReducer

  1. 将设置状态的逻辑 修改 成 dispatch 的一个 action;
  2. 编写 一个 reducer 函数;
  3. 在你的组件中 使用 reducer。

现在组件中有一个 count 的状态,需要增加两个 button ,一个对 count 进行 + 1 的操作,一个对 ount 进行 - 1 的操作。使用设置状态 setCount 的写法是

const [count, setCount] = useState(0)

const handleaAdd = () => {
	setCount(count + 1) 
}

const handleReduce = () => {
	setCount(count - 1)
}

使用Reducer来管理状态需要通过事件处理程序 dispatch 一个 action 来指明用户 “做了什么”。所以在下面,我们不需要通过 setCount 来设置 count ,而是dispatch 一个 “+1”或“ - 1”的action。

const handleaAdd = () => {
	dispatch({
        type: 'add'
    })
}

const handleReduce = () => {
	dispatch({
        type: 'reduce'
    })
}

这时候我们传给 dispatch 的参数是一个 action 对象。这个 action 对象是一个普通的 JavaScript 对象。action 对象中的数据结构是由开发者自己决定的。不过通常会包含“执行了什么操作”的信息,也就是 type 字段。

下一步需要编写一个 reducer 函数。这个 reducer 函数就是我们需要放置状态更新逻辑的地方。reducer接受两个参数—— state 和 action 。并且会返回更新后的参数。并且 reducer 函数可以在组件之外声明。

function countReducer(state, action) {
    if (action.type === 'add') {
        return state + 1
    } else if (action.type === 'reducer') {
        return state - 1
    }
}

一般来说可以使用 swtich 的写法,会提高代码的可读性:

function countReducer(state, action) {
    swtich(action.type) {
        case 'add': return state + 1
        
        case 'reduce': return state - 1
        
        default: return state
    }
}

dispatch函数

useReducer 返回值中第二个元素就是 dispatch 函数。 dispatch 函数允许你更新 state 并触发组件的重新渲染,它需要传入一个 action 作为参数。当调用 dispatch 函数的时候,React就会调用 reducer 函数来根据传入的 action 更新 state 。

注意:

  • dispatch 函数本身没有返回值。
  • dispatch 函数 是为下一次渲染而更新 state。因此在调用 dispatch 函数后读取 state 并不会拿到更新后的值,也就是说只能获取到调用前的值。可以理解为我们使用设置状态 setState 来直接对 state 赋值的情况。
  • 如果你提供的新值与当前的 state 相同),React 会 跳过组件和子组件的重新渲染。

组件中使用

按照上面的例子,最初更新 count 的方法是

import { useState } from "react"

export default function UseReducerMemo () {
  const [count, setCount] = useState(0)

  const handleaAdd = () => {
    setCount(count + 1) 
  }

  const handleReduce = () => {
    setCount(count - 1)
  }

  return (
    <div>
      <div>count: {count}</div>
      <div>
        <button onClick={handleaAdd}>add</button>
        <button onClick={handleReduce}>reduce</button>
      </div>
    </div>
  )
}

这个时候我们创建一个 reducer 函数,将更新 count 的逻辑放在 reducer 函数中。

import { useReducer } from "react"

function countReducer(state, action) {
  if (action.type === 'add') {
      return state + 1
  } else if (action.type === 'reducer') {
      return state - 1
  }
}

export default function UseReducerMemo () {
  const [count, countDispatch] = useReducer(countReducer, 0)

  const handleaAdd = () => {
    countDispatch({
      type: 'add'
    })
  }

  const handleReduce = () => {
    countDispatch({
      type: 'reducer'
    })
  }

  return (
    <div>
      <div>count: {count}</div>
      <div>
        <button onClick={handleaAdd}>add</button>
        <button onClick={handleReduce}>reduce</button>
      </div>
    </div>
  )
}

注意:

  • state 是只读的。即使是对象或数组也不要尝试修改它,而是返回新的对象。否则,React 使用 Object.is 比较更新前后的 state,如果 它们相等就会跳过这次更新。这就会导致页面并没有更新。
  • 调用 dispatch 并不会更新本次渲染函数中的变量。是因为 state 就像一张快照一样,每次渲染函数内部拥有自己独立的props、state和变量。所以 dispatch 之后打印出来的变量仍然没有发生变化。
  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值