当前位置: 首页 > news >正文

【前端知识】React 基础巩固(四十四)——其他Hooks(useContext、useReducer、useCallback)

React 基础巩固(四十四)——其他Hooks(useContext、useReducer、useCallback)

一、useContext的使用

在类组件开发时,我们通过 类名.contextType = MyContext的方式,在类中获取context,多个Context或者在函数式组件中通过MyContext.Consumer方式共享context:

import React, { memo } from 'react'
import { UserContext, ThemeContext } from './context'export default memo(function App() {// 使用Contextreturn (<div><UserContext.Consumer>{value => {return (<h2><ThemeContext.Consumer>{value => {<span></span>}}</ThemeContext.Consumer></h2>)}}</UserContext.Consumer></div>)
})

可以看到,当我们需要使用多个Context时,存在大量繁琐的嵌套代码;而Context Hook能够让我们通过Hook直接获取某个Context的值,如下:

import React, { memo, useContext } from "react";
import { ThemeContext, UserContext } from "./context";export default memo(function App() {// 使用Contextconst user = useContext(UserContext);const theme = useContext(ThemeContext);return (<div><h2>User: {user.name} - {user.age}</h2><h2>Theme: {theme.color} - {theme.size}</h2></div>);
});

可以看到,Context Hook仅用了两行代码就替代了上面繁杂的嵌套代码,十分高效简洁。

二、useReducer的使用

useReducer是useState的一种替代方案,当state的处理逻辑比较复杂,可以使用useReducer来进行拆分,或者当修改state时需要依赖之前的state时,也可以使用useReducer。

useReducer使用的场景非常少,通常用于需要统一管理、修改多个数据的场景。例如,当我们需要对多个数据进行统一处理时,若采用useState,则需要多次定义,而reducer可以对其进行统一定义、修改:

import React, { memo, useReducer, useState } from "react";function reducer(state, action) {switch (action.type) {case "increment":return { ...state, counter: state.counter + 1 };case "decrement":return { ...state, counter: state.counter - 1 };case "add_number":return { ...state, counter: state.counter + action.num };case "sub_number":return { ...state, counter: state.counter - action.num };default:return state;}
}export default memo(function App() {// const [count, setCount] = useState(0);// const [user, setUser] = useState(0);// const [list, setList] = useState(0);const [state, dispatch] = useReducer(reducer, {counter: 0,user: {},list: [],});return (<div>{/* <h2>当前计数:{count}</h2><button onClick={(e) => setCount(count + 1)}>+1</button><button onClick={(e) => setCount(count - 1)}>-1</button><button onClick={(e) => setCount(count + 5)}>+5</button><button onClick={(e) => setCount(count - 5)}>-5</button><button onClick={(e) => setCount(count + 100)}>+100</button> */}<h2>当前计数:{state.counter}</h2><button onClick={(e) => dispatch({ type: "increment" })}>+1</button><button onClick={(e) => dispatch({ type: "decrement" })}>-1</button><button onClick={(e) => dispatch({ type: "add_number", num: 5 })}>+5</button><button onClick={(e) => dispatch({ type: "sub_number", num: 5 })}>-5</button><button onClick={(e) => dispatch({ type: "add_number", num: 100 })}>+100</button></div>);
});

三、useCallback的使用

useCallback实际的目的是为了进行性能优化,useCallback会返回一个函数的memoized(记忆的)值。在依赖不变的情况下,多次定义的时候,返回的值时相同的。

useCallback的性能优化:

  1. 当需要将一个函数传递给子组件时,可使用useCallback进行优化,将优化之后的函数,传递给子组件

    import React, { memo, useCallback, useState } from "react";const HYIncrement = memo(function (props) {const { increment } = props;console.log("HYIncrement被渲染");return (<div><button onClick={increment}>increment + 1</button></div>);
    });export default memo(function App() {const [count, setCount] = useState(0);const [message, setMessage] = useState("hello");// 使用useCallbackconst increment = useCallback(function () {setCount(count + 1);},[count]);// 普通函数// const increment = () => {//   setCount(count + 1);// };return (<div><h2>计数:{count}</h2><button onClick={increment}>+1</button><HYIncrement increment={increment} /><h2>message:{message}</h2><button onClick={(e) => setMessage("world")}>修改 message</button></div>);
    });
  2. 进一步优化

    当count发生改变时,也使用同一个函数

      // 做法一:将count依赖移除掉,缺点:存在闭包陷阱,不依赖count后setCount每次拿到的count并非最新的count// const increment = useCallback(function foo() {//   console.log("increment");//   setCount(count + 1);// }, []);// 做法二:利用useRef,在组件多次渲染时,返回同一个值const countRef = useRef();countRef.current = count;const increment = useCallback(function foo() {console.log("increment");setCount(countRef.current + 1);},[]);
    
http://www.lryc.cn/news/106448.html

相关文章:

  • 华为云hcip核心知识笔记(数据库服务规划)
  • 【有趣的】关于Map的一些小测试
  • 【MATLAB第63期】基于MATLAB的改进敏感性分析方法IPCC,拥挤距离与皮尔逊系数法结合实现回归与分类预测
  • AI 绘画Stable Diffusion 研究(二)sd模型ControlNet1.1 介绍与安装
  • 接口参数设计原则
  • 网络安全防护利器:SK5代理与IP代理的技术对比
  • IDEA删除本地git仓库、创建本地git仓库、关联其他仓库并上传
  • JavaEE简单示例——在使用Tomcat的时候可能出现的一些报错
  • webrtc的线程模型
  • 数据库备份还原-mysqldump、mydumper、xtrabackup、压缩
  • 【黑马程序员前端】JavaScript入门到精通--20230801
  • 100道Java多线程面试题(上)
  • web开发中的安全和防御入门——csp (content-security-policy内容安全策略)
  • 定了!全国2023下半年软考(高级、中级、初级)报名时间汇总
  • Linux下安装配置Redis
  • 深度学习(33)——CycleGAN(2)
  • WeakMap and WeakSet(弱映射和弱集合)
  • 【Vue3基础】组件保持存活、异步加载组件
  • 在 3ds Max 中使用相机映射将静止图像转换为实时素材
  • 如何使用GIL解决Python多线程性能瓶颈
  • k8s概念-深入pod
  • Web服务器实验案例
  • 预警 项目经验BUG
  • 基于RFID技术的猪舍门读卡器
  • 亚马逊店铺的回款周期是多久?
  • 剑指offer19.正则表达式
  • Mac Navicat 16试用脚本
  • 什么是 webpack?
  • #B. 费解的开关
  • Docker离线安装