自学内容网 自学内容网

【React】React18 Hooks 之 useReducer


在这里插入图片描述

React官方文档

useReducer

useReducer是一个 React Hook,可让你向组件添加一个Reducer 。
用法:

const [state, dispatch] = useReducer(reducer, initialArg, init?)
  • reducer:指定状态如何更新的 Reducer 函数,接受两个参数state(状态)和action(操作)两个参数,并返回下一个状态
  • initialArg:初始值,可以是任何类型的值
  • 可选 init:应返回初始状态的初始化函数。如果未指定,则将初始状态设置为initialArg。否则,将初始状态设置为调用的结果init(initialArg)

useReducer返回一个包含两个值的数组:

  • state(当前状态):在第一次渲染期间,它被设置为init(initialArg)或initialArg(如果没有init)
  • dispatch:该dispatch函数可让您将状态更新为不同的值并触发重新渲染

案例1:useReducer不带初始化函数

步骤:
1、定义一个reducer函数,根据不同的action返回不同的状态
2、组件中调用userReducer(reducer,initialArg)
3、调用dispatch({type:“INC”})通知reducer产生一个新的状态,随后更新UI


const idata = {count:0};
function reducer(state, action) {
  console.log(state,"state")
  console.log(action,"action")
  switch (action.type) {
    case "INC":
      return {count:state.count+1}
    case "DEC":
      return {count:state.count-1}
    case "SET":
      return {count:action.payload}
    default:
      return {count:idata}
  }
}
function App() {
  const [state, dispatch] = useReducer(reducer, idata);
  return (
    <div className="App">
      this is App
      {state.count}
      <button onClick={() => dispatch({ type: "INC" })}>+</button>
      <button onClick={() => dispatch({ type: "DEC" })}>-</button>
      <button onClick={() => dispatch({ type: "SET", payload: 100 })}>update</button>
    </div>
  );
}

export default App;

案例2:useReducer带初始化函数

设置initData为初始化函数,设置state初始状态

#App.js
import Son from "./Son.js";
function App() {
return (
  <div className="App">
  <Son idata={{count:1}}></Son>
  </div>
);
  }
  
  export default App;
  
#Son.js
import { useReducer } from "react";

const initData=()=>{
  return {count:0}
}

function reducer(state, action) {
  console.log(state,"state")
  console.log(action,"action")
  switch (action.type) {
    case "INC":
      return {count:state.count+1}
    case "DEC":
      return {count:state.count-1}
    case "SET":
      return {count:action.payload}
     default:
      return initData() 
  }
}

const  Son = ({idata})=> {
  console.log(idata,"idata")
  const [state, dispatch] = useReducer(reducer, idata,initData);
  return (
    <div className="App">
      this is App
     <div>Count: {state.count}</div>
      <button onClick={() => dispatch({ type: "INC" })}>+</button>
      <button onClick={() => dispatch({ type: "default" })}>default</button>
      <button onClick={() => dispatch({ type: "DEC" })}>-</button>
      <button onClick={() => dispatch({ type: "SET", payload: 100 })}>update</button>
    </div>
  );
}

export default Son;

注意事项1:dispatch函数不会改变正在运行的代码的状态

点击update按钮,handler函数触发之后,页面Count显示为100,但是打印出来state.count为0

dispatch函数不会改变正在运行的代码的状态,更新状态会请求使用新状态值进行另一次渲染,但不会影响state已在运行的事件处理程序中的 JavaScript 变量。

#Son.js
import { useReducer } from "react";
const initData = () => {
  return { count: 0 }
}
function reducer(state, action) {

  switch (action.type) {
    case "INC":
      return { count: state.count + 1 }
    case "DEC":
      return { count: state.count - 1 }
    case "SET":
      return { count: action.payload }
    default:
      return initData()
  }
}

const Son = ({ idata }) => {
const [state, dispatch] = useReducer(reducer, idata, initData);

const handler =()=>{
    dispatch({ type: "SET", payload: 100 })
    console.log(state.count,"state")
    setTimeout(()=>{
      console.log(state.count,"state")
    },1000)
  }
  return (
    <div className="App">
      this is App
     <div>Count: {state.count}</div>
      <button onClick={() => dispatch({ type: "INC" })}>+</button>
      <button onClick={() =>  dispatch({ type: "default" })}>default</button>
      <button onClick={() => dispatch({ type: "DEC" })}>-</button>
      <button onClick={() => handler()}>update</button>
    </div >
  );
}

export default Son;

注意事项2:获取dispatch函数触发后 JavaScript 变量的值

执行reducer(state, action)之后,就可以拿到最新的变量的值

  const handler =()=>{
    let action = { type: "SET", payload: 100 };
    dispatch(action)
    console.log(state,"state") //打印0
    setTimeout(()=>{
      console.log(state,"state")  //打印0
    },1000)
    const nextState = reducer(state, action);
    console.log(nextState,'nextState')  //打印100
  }

注意事项3:触发了reducer,但页面没有更新

直接更改状态中的对象或数组,并不会重新渲染。因为下一个状态等于前一个状态,则React 将忽略您的更新Object.is,指向的还是同一个引用地址。所以需要始终更新状态中的对象和状态中的数组。如下:

function reducer(state, action) {
  switch (action.type) {
    case 'incremented_age': {
      // ✅ Correct: creating a new object
      return {
        ...state,
        age: state.age + 1
      };
    }
    case 'changed_name': {
      // ✅ Correct: creating a new object
      return {
        ...state,
        name: action.nextName
      };
    }
    // ...
  }
}


原文地址:https://blog.csdn.net/qq_38951259/article/details/140211795

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!