React中使用useReducer

React中使用useReducer


1.Reducer

*使用函数组件来对state的数据进行多次修改的话,就可以使用useReducer来对其内容进行简化。

const [count, setCount] = useState(1)

// 增加
const addHandler = () => {
    setCount(prevState => prevState + 1 )
}

// 减少
const subHandler = () => {
    setCount(prevState => prevState - 1 )
}

return (
    <div>
        <button onClick={subHandler}> - </button>
            {count}
        <button onClick={addHandler}> + </button>
    </div>
)

每次调用的话都要setCount

useReducer(reducer, initialArg, init)

useRecucer有三个参数

/*

参数:

​ reducer: 函数 该函数的返回值会成为state的 新值

​ initialArg:state的初始值,作用和useState()的值是一样的

​ reducer在执行的时候会受到两个参数:

​ > 第一个参数为当前最新的state

​ > action 需要一个对象,在对象中存储dispatch的指令

返回值:

​ 数组:

​ 第一个参数:state 用来获取state的值

​ 第二个参数:state 修改的派发器

​ 具体的修改行为将会由另外一个函数(reducer)执行

const [count, countDispatch] = useReducer(()=>{}, 1)

*/

  • 增加

    const [count, countDispatch] = useReducer((state, action)=>{
    	// 第一个参数为当前最新的state
    	console.log("执行reducer", state)
        console.log("执行reducer", action)
        
        // 可以根据action中不同的type来执行不同的操作
        // if(action.type === 'add'){
        //   return state + 1
    	// }else if (action.type === 'sub') {
        //   return state - 1        
        // }
        // return state
        switch(action.type){
            case 'add' :
                return state + 1;
            case 'sub' : 
                return state - 1;
            default:
                return state
               }
        
    	// return state + 1   // 增加
    }, 1)
    
    const addHandle = () => {
    	countDispatch({type:'add'})
    }
    
    const subHandle = () => {
    	countDispatch({type:'sub'})
    }
    
  • 注:

    • 为了避免reducer会重复创建,通常reducer会定义在组件的外部,以减少它重复创建的次数!!!!!!!!!!!!!!

    • useReducer会返回由两个值组成的数组:
      1.当前的state,初始值

      2.dispatch函数,可以根据交互来修改state的值

// 在组件外部
const countReducer = (state, reducer) => {
    switch(action.type){
        case 'add' :
            return state + 1;
        case 'sub' : 
            return state - 1;
        default:
            return state
    }
}
// --------------------------------------------
// 在组件里面
const [count, countDispatch] = useReducer(countReducer, 1)
const addHandle = () => {
	countDispatch({type:'add'})
}
const subHandle = () => {
	countDispatch({type:'sub'})
}

完整代码:

import React, { useState, useReducer } from "react";
import Bottombar from "../components/Bottombar/Bottombar";
import Map from "../components/Map";
import { Outlet, Link } from "react-router-dom";
import "./phone.css";

// 为了避免回調函數reducer会重复渲染,因此要定义在组件外面
// 在组件外面
const reducer = (state, action) => {
  console.log("state", state);
  console.log("action", action);
  switch (action.type) {
    case "add":
      return state + 1;
    case "sub":
      return state - 1;

    // 默認返回
    default:
      return state;
  }
};

const Phone = () => {
  // 使用useState和useReducer
  const [count, setcount] = useState(1);

  const SubCount = () => {
    console.log("-1");
    setcount((prevState) => prevState - 1);
  };

  const AddCount = () => {
    console.log("+1");
    setcount((prevState) => prevState + 1);
  };

  // useReducer
  // const [num, numDispatch] = useReducer(reducer, 11);
  const [num, numDispatch] = useReducer(reducer, 11);

  const SubReducerCount = () => {
    numDispatch({ type: "sub" });
  };

  const AddReducerCount = () => {
    numDispatch({ type: "add" });
  };

  return (
    <div>
      Phone
      <br></br>
      {/* <h1 className="bgc">test</h1> */}
      <Link to="/phone/era" className="red">
        eraeraeraera
      </Link>
      --------------------
      <Link to="/phone/erc" className="red">
        ercercercerc
      </Link>
      <Outlet></Outlet>
      {/* <Map></Map> */}
      <div>
        <div className="title">使用useState和useReducer</div>
        <div className="title">--使用useState</div>
        <div className="box">
          <button onClick={SubCount}>-1</button>
          <div className="num">{count}</div>
          <button onClick={AddCount}>+1</button>
        </div>

        <div className="title">--使用useReducer</div>
        <div className="box">
          <button onClick={SubReducerCount}>-1</button>
          <div className="num1">{num}</div>
          <button onClick={AddReducerCount}>+1</button>
        </div>
      </div>
      <Bottombar></Bottombar>
    </div>
  );
}

export default Phone

在这里插入图片描述

如果是对象的话,以下方式写会有问题!!!!

// 在组件外面
const reducer = (state, action) => {
  console.log("state", state);
  console.log("action", action);
  switch (action.type) {
    case "add":
      return state.age + 1;
    case "sub":
      return state.age - 1;

    // 默認返回
    default:
      return state.age;
  }
};
 const [num, numDispatch] = useReducer(reducer, {
    name: '李白',
    age: 22
  });

在这里插入图片描述

解决:
// 为了避免回調函數reducer会重复渲染,因此要定义在组件外面
// 在组件外面
const reducer = (state, action) => {
  console.log("state", state);
  console.log("action", action);
  switch (action.type) {
    case "add":
      return {
        name: 'author+',
        age: state.age + 1
      };
    case "sub":
      return {
        name: 'author-',
        age: state.age - 1
      };

    // 默认返回
    default:
      return {
        name: '李白',
        age: state.age
      };
  }
};

在这里插入图片描述
注意:state是只读的,不管是对象还是数组都不能去修改它,正确写法是返回新的对象

// 不可取的     ×
switch (action.type) {
    case "add":
      state.age = state.age + 1
      return state;
      ......

// 正确写法:√
switch (action.type) {
    case "add":
      return {
        name: 'author+',
        age: state.age + 1
      };
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值