7.react useReducer使用与常见问题

news/2024/7/15 17:45:43 标签: react.js, javascript, ecmascript

useReducer函数

1. useState的替代方案.接收一个(state, action)=>newState的reducer,
并返回当前的state以及与其配套的dispatch方法

2. 在某些场景下,useReducer会比useState更加适用,例如state逻辑较为复杂,
且**包含多个子值**,或者下一个state依赖于之前的state等

清楚useReducer场景?
与useState区别?
不足之处,只能处理同步
如何实现异步,提供了两个案例?

1. 用useState做登录

一组响应式数据有关联关系,可以做成一个整体,使用useReducer将其作为一个整体实现

<body>
  <div id="app"></div>
  <script type="text/babel">javascript">
    let app = document.querySelector('#app');
    let root = ReactDOM.createRoot(app);
    let { useState } = React;

    // 用useState做登录
    // >  一组响应式数据有关联关系,可以做成一个整体,使用useReducer将其作为一个整体实现
    let Welcome = (props) => {  
      const [ isLogin, setLogin ] = useState(true);
      const [ isLogout, setLogout ] = useState(false);
      const handleLogin= () => {
        setLogin(true);
        setLogout(false);
      }

      const handleLogout= () => {
        setLogout(true);
        setLogin(false);
      }
      return (
        <div>
         {
          isLogin?
          <button onClick={handleLogout}>登出</button>:
          <button onClick={handleLogin}>登录</button>
         }
        </div>
      );
    }
    
    let element = (
      <Welcome />
    );
    root.render(element);
  </script>
</body>

2. 改为useReducer

<body>
  <div id="app"></div>
  <script type="text/babel">javascript">
    /* 
    useReducer改写
    */

    let app = document.querySelector('#app');
    let root = ReactDOM.createRoot(app);
    let { useReducer } = React;


    let loginState = {
      isLogin: true,
      isLogout: false
    }

    // 不足: 处理同步action
    let loginReducer = (state, action) => {
      switch (action.type) {
        case 'login':
          return { isLogin: true, isLogout: false }
        case 'logout':
          return { isLogin: false, isLogout: true }
        default:
          throw new Error()
      }
    }
    // 用useReducer做登录
    // > 根据类型,决定不同的state处理变化
    let Welcome = (props) => {
      const [state, loginDispatch] = useReducer(loginReducer, loginState);
      const handleLogin = () => {
        loginDispatch({ type: 'login' })
      }

      const handleLogout = () => {
        loginDispatch({ type: 'logout' })
        // loginDispatch({ type: 'logout' ,payload:''})
      }
      return (
        <div>
          {
            state.isLogin ?
              <button onClick={handleLogout}>登出</button> :
              <button onClick={handleLogin}>登录</button>
          }
        </div>
      );
    }

    let element = (
      <Welcome />
    );
    root.render(element);
  </script>
</body>

不足

useReduer只处理同步请求,对异步请求如何处理?
https://zhuanlan.zhihu.com/p/114367502
在这里插入图片描述

在这里插入图片描述

3.1 异步封装

组件页面
const init = { dataList:[] };//初始化dataState
 
const [state,dispatch] = useReducer(reducer,init);
 
useEffect(() => {
    //发送网络请求
    axios.get("/user?ID=123").then(res => {
        dispatch({
            type:ACTION_TYPE.GETDATA,
            payload:res.data //后端返回的数据
        })
    })
},[]);
 
//使用 state.dataList 渲染页面
在reducer页面

function reducer(state,action){
    switch(action.type){
        case "getData":
            return { //根据需求对数据做出操作,这里将返回的数据与初始化的数据合并
                ...state,
                dataList:action.payload 
            };
}    
 
export default reducer;

3.2 异步封装

初始化直接执行获取数据

import React, { useEffect, useState, useReducer } from "react";
import ReactDom from "react-dom";
import $ from "jquery";

const useProduct = () => {
  const [data, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case "a":
        return action.value;
      default:
        return [];
    }
  }, []);

  useEffect(() => {
    $.ajax({
      url: "http://suggest.taobao.com/sug?code=utf-8&q=袜子",
      dataType: "jsonp",
      jsonp: "callback",
      success: (data) => {
        dispatch({
          type: 'a',
          value: data.result
        });
      },
      error: data => dispatch({type: 'error', msg: data})
    });
  }, []);

  return data;
};

const Index = () => {
  const data = useProduct();

  return <>{data.length}</>;
};

ReactDom.render(<Index />, document.getElementById("root"));

官网:
1. https://zh-hans.legacy.reactjs.org/docs/hooks-reference.html#usereducer


http://www.niftyadmin.cn/n/4987357.html

相关文章

Ceph IO流程及数据分布

1. Ceph IO流程及数据分布 1.1 正常IO流程图 步骤&#xff1a; client 创建cluster handler。client 读取配置文件。client 连接上monitor&#xff0c;获取集群map信息。client 读写io 根据crshmap 算法请求对应的主osd数据节点。主osd数据节点同时写入另外两个副本节点数据。…

28 - restful -request和response

response: 需要定制返回字段的格式 request: 需要校验前端传来的参数 代码示例: 1. 创建模型类 from datetime import datetime from ext import dbclass User(db.Model):id db.Column(db.Integer, primary_keyTrue, autoincrementTrue)username db.Colu…

光模块温度报警的原因及解决措施

光模块是数据中心网络中的关键组件&#xff0c;它们在高温环境下可能会受到影响。如果光模块的温度超过正常范围&#xff0c;可能会导致网络故障和光模块损坏。因此&#xff0c;了解光模块的温度报警并采取相应的解决措施非常重要。 一、光模块温度报警的原因 光模块温度报警通…

node 如何下载任意版本

开门见山啦 第一步&#xff1a;打开node官网 Node.js 第二步&#xff1a;点击下载 进入下面的页面&#xff0c;然后往下滑&#xff0c;点击 All download options 查看以往所有的版本号&#xff1a; 这样就可以按自己的需求下载对应的node版本啦 或者 &#xff1a; 最简单…

Google登录SDK

一、接入的准备工作 官方文档链接地址&#xff1a;开始使用一键登录和注册 按照步骤进行接入即可 二、项目参考&#xff08;Unity项目&#xff09; 注意&#xff1a;代码版本如果不适用新的Google API 请自行参考最新版本接口 SDKGoogleSignInActivity 主要用于登录的代码。Un…

C/C++与C#随笔

1、C/C与C#中的值类型和引用类型 /* C/C code */ int i0; //声明值类型变量i,值为0 int &i_refi; //声明引用类型变量i_ref,是i的引用,与i等价,可作为引用传参int *i_ptr&i; //声明指针类型变量i_ptr&#xff0c;指向 int *i_ptr2&i_ref; //与…

移动数据安全案例(MAG)| 好的方案是恰到好处的平衡

某基金公司是由国有商业银行直接发起设立并控股的合资基金管理公司&#xff0c;服务于超过5000万客户&#xff0c;其资产管理规模近2万亿。作为国内头部基金公司&#xff0c;在网络安全和数据安全的建设上已经非常完善。目前已在办公网敏感数据的创建、流转、存储等数据安全生命…

单片机通用学习-​什么是寄存器?​

什么是寄存器&#xff1f; 寄存器是一种特殊的存储器&#xff0c;主要用于存储和检查微机的状态。CPU寄存器用于存储和检查CPU的状态&#xff0c;具体包括计算中途数据、程序因中断或子程序分支时的返回地址、计算结果为零时的负值、计算结果为零时的信息、进位值等。 由于CP…