React复习

文章目录

    • 常用的Hooks
      • useState
      • useReducer
      • useRef
      • useContext
      • useMemo
      • useCallback
      • useEffect
    • 组件通信
      • Props(属性)
      • Ref(引用)
      • Context(上下文)
      • State(状态)
      • 回调函数
      • Event Bus(事件总线)
      • Custom Hooks(自定义钩子)
      • Redux
    • 生命周期
      • React 17 之前:
      • React 17 之后:
      • 常用的生命周期方法:
        • Class 组件中常用:
        • Function 组件中使用(Hooks):
      • 不常用的生命周期方法:
        • Class 组件中不常用:
        • Class 组件中特有的:

好多年没使react了,有些忘了,简单复习一下…

常用的Hooks

useState

用于管理组件内部的状态,允许在函数组件中添加和管理 state。

import React, { useState } from 'react';function Counter() {const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
}

useReducer

管理复杂的状态逻辑,特别是当 state 逻辑涉及到多个子值,或者下一个 state 依赖于前一个 state 时。

import React, { useReducer } from 'react';const initialState = { count: 0 };
function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:return state;}
}function Counter() {const [state, dispatch] = useReducer(reducer, initialState);return (<>Count: {state.count}<button onClick={() => dispatch({ type: 'decrement' })}>-</button><button onClick={() => dispatch({ type: 'increment' })}>+</button></>);
}

useRef

在组件中直接访问DOM 元素;

import React, { useRef } from 'react';function TextInputWithFocusButton() {const inputEl = useRef(null);const onButtonClick = () => {// `current` 指向挂载的文本输入元素inputEl.current.focus();};return (<><input ref={inputEl} type="text" /><button onClick={onButtonClick}>Focus the input</button></>);
}

在组件的不同渲染之间保持一个可变的值,并且这个值不会触发组件的重新渲染。

import React, { useRef, useState, useEffect } from 'react';function Timer() {const intervalRef = useRef();const [count, setCount] = useState(0);useEffect(() => {intervalRef.current = setInterval(() => {setCount((c) => c + 1);}, 1000);return () => clearInterval(intervalRef.current);}, []);return (<div><p>Count: {count}</p><button onClick={() => clearInterval(intervalRef.current)}>Stop Timer</button></div>);
}

useContext

在组件之间共享状态,而不必通过 “props下钻” 层层传递。

import React, { useContext } from 'react';
const ThemeContext = React.createContext('light');function ThemedButton() {const theme = useContext(ThemeContext);return <button theme={theme}>I am styled by theme context!</button>;
}

useMemo

缓存计算密集型函数的返回值。
当你把一些计算开销较大的值或者组件作为依赖项传递给其他组件或者渲染逻辑时,使用 useMemo 可以避免不必要的计算,从而提高性能。

import React, { useMemo } from 'react';function expensiveCalculation(num) {console.log('Calculating...');for (let i = 0; i < 1000000; i++) {} // 模拟一个耗时计算return num * 2;
}function MyComponent({ a, b }) {const memoizedValue = useMemo(() => {return expensiveCalculation(a);}, [a]); // 只有 a 改变时,才会重新计算return (<div>{memoizedValue}<p>Dependency: {b}</p></div>);
}

useCallback

缓存函数。
当你将一个函数传递给子组件或者作为 props 传递时,使用 useCallback 可以避免不必要的渲染,从而提高性能。

import React, { useCallback, useState } from 'react';function MyComponent() {const [count, setCount] = useState(0);const handleIncrement = useCallback(() => {setCount((c) => c + 1);}, []); // 由于 setCount 是稳定的,所以这里不需要依赖项const handleDecrement = useCallback(() => {setCount((c) => c - 1);}, []); // 同上return (<div><button onClick={handleIncrement}>Increment</button><button onClick={handleDecrement}>Decrement</button><p>Count: {count}</p></div>);
}

useEffect

允许在函数组件中执行副作用操作,如数据获取、订阅或手动更改 React 组件中的 DOM。

import React, { useState, useEffect } from 'react';function ExampleComponent() {useEffect(() => {// 这个函数会在组件每次渲染后执行// 可以在这里执行副作用操作return () => {// 这个清理函数会在组件卸载前执行};}, []); // 空数组表示这个 effect 只会在组件挂载时执行一次return <div>Hello, world!</div>;
}

组件通信

Props(属性)

最常见的方式是通过props属性将数据从父组件传递给子组件。父组件可以在子组件的标签中传递props,子组件通过props接收数据。

// ParentComponent.js
import ChildComponent from './ChildComponent';function ParentComponent() {const data = 'Hello from parent';return <ChildComponent data={data} />;
}// ChildComponent.js
function ChildComponent(props) {return <div>{props.data}</div>;
}

Ref(引用)

可以使用ref来直接访问子组件的实例,并通过实例方法传递数据。

// ParentComponent.js
import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';function ParentComponent() {const childRef = useRef();const sendDataToChild = () => {childRef.current.handleData('Hello from parent');};return (<><ChildComponent ref={childRef} /><button onClick={sendDataToChild}>Send Data</button></>);
}// ChildComponent.js
import React, { forwardRef, useImperativeHandle } from 'react';const ChildComponent = forwardRef((props, ref) => {const handleData = (data) => {console.log(data);};useImperativeHandle(ref, () => ({handleData}));return <div>Child Component</div>;
});export default ChildComponent;

Context(上下文)

Context允许在组件树中传递数据,而不必一级一级手动传递props。适用于跨多层级的组件传递数据。

// DataContext.js
import React from 'react';const DataContext = React.createContext();export default DataContext;// ParentComponent.js
import DataContext from './DataContext';
import ChildComponent from './ChildComponent';function ParentComponent() {const data = 'Hello from parent';return (<DataContext.Provider value={data}><ChildComponent /></DataContext.Provider>);
}// ChildComponent.js
import DataContext from './DataContext';function ChildComponent() {return (<DataContext.Consumer>{data => <div>{data}</div>}</DataContext.Consumer>);
}

State(状态)

通过组件的状态来传递数据。父组件可以将数据存储在自身的状态中,然后通过props将数据传递给子组件。

// ParentComponent.js
import ChildComponent from './ChildComponent';function ParentComponent() {const [data, setData] = useState('Hello from parent');return <ChildComponent data={data} />;
}// ChildComponent.js
function ChildComponent(props) {return <div>{props.data}</div>;
}

回调函数

父组件可以通过回调函数将数据传递给子组件。子组件可以调用回调函数来传递数据给父组件。

// ParentComponent.js
import ChildComponent from './ChildComponent';function ParentComponent() {const handleData = (data) => {console.log(data);};return <ChildComponent sendData={handleData} />;
}// ChildComponent.js
function ChildComponent(props) {const sendDataToParent = () => {props.sendData('Hello from child');};return <button onClick={sendDataToParent}>Send Data</button>;
}

Event Bus(事件总线)

通过事件总线来进行组件间的通信,一个组件发送事件,另一个组件监听事件并做出相应处理。

// EventBus.js
import { EventEmitter } from 'events';const eventBus = new EventEmitter();export default eventBus;// ParentComponent.js
import eventBus from './EventBus';
import ChildComponent from './ChildComponent';function ParentComponent() {const sendDataToChild = () => {eventBus.emit('sendData', 'Hello from parent');};return (<><ChildComponent /><button onClick={sendDataToChild}>Send Data</button></>);
}// ChildComponent.js
import React, { useEffect } from 'react';
import eventBus from './EventBus';function ChildComponent() {useEffect(() => {eventBus.on('sendData', (data) => {console.log(data);});return () => {eventBus.off('sendData');};}, []);return <div>Child Component</div>;
}

Custom Hooks(自定义钩子)

通过自定义钩子来共享逻辑和状态,并在不同组件中使用。可以将数据存储在自定义钩子中,然后在需要的组件中使用。

// UseData.js
import { useState } from 'react';const useData = () => {const [data, setData] = useState('Hello from custom hook');return { data, setData };
};export default useData;// ParentComponent.js
import useData from './UseData';
import ChildComponent from './ChildComponent';function ParentComponent() {const { data } = useData();return <ChildComponent data={data} />;
}// ChildComponent.js
function ChildComponent(props) {return <div>{props.data}</div>;
}

Redux

在React中结合Redux进行状态管理,通常需要使用react-redux库来连接Redux Store和React组件。

  • 创建Redux Store:
// store.js
import { createStore } from 'redux';
import rootReducer from './reducers';const store = createStore(rootReducer);export default store;
  • 定义Reducer:
// reducers.js
const initialState = {count: 0
};const counterReducer = (state = initialState, action) => {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };case 'DECREMENT':return { ...state, count: state.count - 1 };default:return state;}
};export default counterReducer;
  • 连接Redux Store和React组件:
// App.js
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';const App = () => {const count = useSelector(state => state.count);const dispatch = useDispatch();const increment = () => {dispatch({ type: 'INCREMENT' });};const decrement = () => {dispatch({ type: 'DECREMENT' });};return (<div><h1>Count: {count}</h1><button onClick={increment}>Increment</button><button onClick={decrement}>Decrement</button></div>);
};export default App;
  • Provider组件:在根组件中使用Provider组件将Redux Store传递给整个应用程序。
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';ReactDOM.render(<Provider store={store}><App /></Provider>,document.getElementById('root')
);

状态管理还有很多其他的方式(特别卷)。比如: Zustand、MobX等等


生命周期

挂载(Mounting)、更新(Updating)和卸载(Unmounting)的过程。

React 17 之前:

挂载阶段(Mounting)

  • constructor(): 构造函数,在组件被创建时调用,用于初始化state、可以接收一个父组件传来的props、绑定事件处理方法。
  • componentWillMount(已弃用): 组件将要挂载
  • render(): 在这里面我们会写一些html标签及自定义的函数,render执行完后便会将这些语句对应渲染到浏览器上面。
  • componentDidMount(): 组件挂载后调用,通常用于进行异步数据获取、订阅事件等操作。

更新阶段(Updating)

  • componentWillReceiveProps(已弃用): 在组件接收到新的 props 之前调用。
  • shouldComponentUpdate(): 决定是否重新渲染组件,在接收新props或state时调用,用于性能优化。 当更新state值的时候会执行这个函数,比如this.setState({})。
  • componentWillUpdate(已弃用): 会在组件接收到新的 props 或 state 并即将重新渲染之前被调用。
  • render(): 和初始化时候执行的那个render一样,只是这里是更新值的,所以dom节点会重新更新一下。
  • componentDidUpdate(): 组件更新后调用,通常用于处理DOM操作、网络请求等。

卸载阶段(Unmounting)

  • componentWillUnmount(): 组件卸载前调用,用于清理定时器、取消订阅等操作。

React 17 之后:

挂载阶段(Mounting)

  • constructor()
  • static getDerivedStateFromProps: React 会在初始挂载和后续更新时调用 render 之前调用它。它应该返回一个对象来更新 state,或者返回 null 就不更新任何内容。挂载阶段只调用一次,用于初始化 state。
  • render()
  • componentDidMount()

更新阶段(Updating)

  • static getDerivedStateFromProps: 更新阶段每次组件接收到新的 props 时都会被调用。
  • shouldComponentUpdate()
  • render()
  • getSnapshotBeforeUpdate: 会在 React 更新 DOM 之前时直接调用它。它使你的组件能够在 DOM 发生更改之前捕获一些信息(例如滚动的位置)。此生命周期方法返回的任何值都将作为参数传递给 componentDidUpdate。
  • componentDidUpdate()

卸载阶段(Unmounting)

  • componentWillUnmount()

在这里插入图片描述

除了上述生命周期方法,还有componentDidCatch()用于捕获组件树中的错误。此外,React Hooks也提供了函数式组件中的生命周期替代方案,如useEffect()用于处理副作用。

  • componentDidCatch:
import React, { Component } from 'react';class ErrorBoundary extends Component {constructor(props) {super(props);this.state = { hasError: false };}componentDidCatch(error, info) {this.setState({ hasError: true });console.error('Error caught by ErrorBoundary:', error, info);}render() {if (this.state.hasError) {return <h1>Something went wrong.</h1>;}return this.props.children;}
}export default ErrorBoundary;
  • useEffect: 在函数式组件中,可以使用React Hooks来替代类组件中的生命周期方法。
import { useState, useEffect } from 'react';const FunctionalComponent = () => {const [count, setCount] = useState(0);// 相当于 componentDidMount 和 componentDidUpdateuseEffect(() => {console.log('Component is mounted or updated');// 清理函数,相当于 componentWillUnmountreturn () => {console.log('Component is about to unmount');};}, [count]); // 仅在count发生变化时触发// 模拟 shouldComponentUpdateconst shouldUpdate = (nextProps, nextState) => {if (nextState.count !== count) {return true;}return false;};const handleClick = () => {setCount(count + 1);};return (<div><p>Count: {count}</p><button onClick={handleClick}>Increment Count</button></div>);
};export default FunctionalComponent;

常用的生命周期方法:

在这里插入图片描述

Class 组件中常用:
  • constructor(): 用于初始化 state 和绑定方法。
  • render(): 必须的方法,用于渲染组件。
  • componentDidMount(): 在组件挂载后被调用,常用于进行 API 调用、订阅等。
  • componentDidUpdate(prevProps, prevState): 在组件更新后被调用,可以用于比较 props 和 state 的变化。
  • componentWillUnmount(): 在组件卸载前被调用,常用于清理资源,如取消订阅、清除定时器等。
Function 组件中使用(Hooks):
  • useEffect(): 用于在函数组件中执行副作用操作,类似于 componentDidMount、componentDidUpdate 和 componentWillUnmount。
  • useLayoutEffect(): 类似于 useEffect,但它会在所有的 DOM 变更之后同步调用 effect,适用于读取 DOM 布局并同步触发重渲染的情况。

不常用的生命周期方法:

Class 组件中不常用:
  • UNSAFE_componentWillMount(): 虽然可用,但官方不推荐使用,其用途通常可以在 componentDidMount 中实现。
  • UNSAFE_componentWillReceiveProps(nextProps): 虽然可用,但官方不推荐使用,推荐使用 getDerivedStateFromProps 或在 componentDidUpdate 中处理新的 props。
  • UNSAFE_componentWillUpdate(nextProps, nextState): 虽然可用,但官方不推荐使用,其用途通常可以在 componentDidUpdate 中实现。
Class 组件中特有的:
  • getDerivedStateFromProps(props, state): 这是一个静态方法,用于根据 props 更新 state,在组件挂载和更新时都会被调用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/445536.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络面试题——第三篇

1. TCP超时重传机制是为了解决什么问题 因为TCP是一种面向连接的协议&#xff0c;需要保证数据可靠传输。而在数据传输过程中&#xff0c;由于网络阻塞、链路错误等原因&#xff0c;数据包可能会丢失或者延迟到达目的地。因此&#xff0c;若未在指定时间内收到对方的确认应答&…

protobufJavascrip编码解码演示

protobuf&Javascrip编码解码演示 start 写一下 protobuf 相关知识记录在 python 环境和 js 环境中如何处理 protobuf。 1. protobuf是什么&#xff1f; 1.1 介绍 Protocol Buffers(简称Protobuf) &#xff0c;是Google出品的序列化框架&#xff0c;与开发语言无关&…

【数据结构】邻接表

一、概念 邻接表是一个顺序存储与链式存储相结合的数据结构&#xff0c;用于描述一个图中所有节点之间的关系。 若是一个稠密图&#xff0c;我们可以选择使用邻接矩阵&#xff1b;但当图较稀疏时&#xff0c;邻接矩阵就显得比较浪费空间了&#xff0c;此时我们就可以换成邻接…

JavaSE——认识异常

1.概念 在生活中&#xff0c;人有时会生病&#xff0c;在程序中也是一样&#xff0c;程序猿是一帮办事严谨、追求完美的高科技人才。在日常开发中&#xff0c;绞尽脑汁将代码写的尽善尽美&#xff0c;在程序运行过程中&#xff0c;难免会出现一些奇奇怪怪的问题。有时通过代码很…

【Unity】Unity中接入Admob聚合广告平台,可通过中介接入 AppLovin,Unity Ads,Meta等渠道的广告

一、下载Google Admob的SDK插件 到Google Admob官网中&#xff0c;切换到Unity平台 进来之后是这样&#xff0c;注意后面有Unity标识&#xff0c;然后点击下载&#xff0c;跳转到github中&#xff0c;下载最新的Admob插件sdk&#xff0c;导入到Unity中 二、阅读官方文档&…

【Linux】Screen的使用:新建、退出、再登陆

Linux screen 命令详解与使用指南 在Linux系统中&#xff0c;screen 是允许用户在单个终端会话中运行多个进程&#xff0c;并能在会话之间切换。 适用情况&#xff1a;screen 特别适用于远程登录&#xff08;如通过SSH&#xff09;时&#xff0c;确保即使网络连接断开&#x…

国产化ERP是什么?与SAP相比有何优势所在?

前段时间和一个工厂老板聊起来&#xff0c;他正为公司的 ERP 系统发愁呢。他们企业现在用的系统有点跟不上发展节奏了&#xff0c;在考虑换新的。但到底是继续选国际大牌 SAP 呢&#xff0c;还是试试国产化的 ERP 呢&#xff1f;这可真是个难题。这也不是他一家企业的困扰&…

如何通过钢筋计来优化施工安全

在现代建筑工程中&#xff0c;施工安全一直是首要关注的问题。特别是在高层建筑、桥梁和地下工程等复杂结构中&#xff0c;确保钢筋的正确安装和稳定性能&#xff0c;直接关系到工程的整体安全性和耐久性。钢筋计作为一种专门用于测量和监测钢筋应力和应变的设备&#xff0c;其…

使用node+prisma+socket+vue3实现一个群聊功能,拓展功能:使用lottie实现入场动画

使用nodeprisma和vue3实现一个群聊功能 后端代码编写 node环境初始化 新建一个空文件夹node&#xff0c;初始化node环境 npm init -y修改 packages.json&#xff0c;添加 type 为 module&#xff0c;删除 main {"name": "node","version": …

【C语言复习】分支和循环

【C语言复习】分支和循环 1. if语句1.1 if1.2 else1.3分支中包含多条语句1.4嵌套if1.5悬空else问题 2.关系操作符3. 条件操作符4.逻辑操作符&#xff1a;&& 、|| 、!4.1 逻辑取反运算符4.2 与运算符4.3或运算符4.4 练习&#xff1a;闰年的判断4.5短路 5.switch 语句5.1…

python爬虫 - 进阶正则表达式

&#x1f308;个人主页&#xff1a;https://blog.csdn.net/2401_86688088?typeblog &#x1f525; 系列专栏&#xff1a;https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、匹配中文 &#xff08;一&#xff09;匹配单个中文字符 &#xff08;二…

Java项目实战II基于Java+Spring Boot+MySQL的服装销售平台(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在当今数字…

uniapp-小程序开发0-1笔记大全

uniapp官网&#xff1a; https://uniapp.dcloud.net.cn/tutorial/syntax-js.html uniapp插件市场&#xff1a; https://ext.dcloud.net.cn/ uviewui类库&#xff1a; https://www.uviewui.com/ 柱状、扇形、仪表盘库&#xff1a; https://www.ucharts.cn/v2/#/ CSS样式&…

硬件开发笔记(三十一):TPS54331电源设计(四):PCB布板12V转5V电路、12V转3.0V和12V转4V电路

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/142757509 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV…

ansible 流程控制

目录 1.流程控制 2.handlers触发器 2.1使用handlers案例 3.when 判断 3.1 案例1 用于给task设置条件 满足或者不满足运行对应模块 3.2 案例2 如果系统是centos则安装sl&#xff0c;cowsay 如果是unbantu则安装cmatrix 4.循环 4.1案例 1.流程控制 hand…

Git客户端使用之TortoiseGit和Git

git客户端有两个分别是TortoiseGit和Git Git用于命令行TortoiseGit用于图形界面。无论是Git还是TortoisGit都需要生成公/私钥与github/gitlab建立加密才能使用。 一、先介绍Git的安装与使用 1、下载与安装 安装Git-2.21.0-64-bit.exe(去官网下载最新版64位的)&#xff0c;安…

SpringMVC2~~~

目录 数据格式化 基本数据类型可以和字符串自动转换 特殊数据类型和字符串间的转换 验证及国际化 自定义验证错误信息 细节 数据类型转换校验核心类DataBinder 工作机制 取消某个属性的绑定 中文乱码处理 处理json和HttpMessageConverter 处理Json-ResponseBody 处理…

Python精选200Tips:186-190

针对序列&#xff08;时间、文本&#xff09;数据的网络结构 续 P186-- 双向LSTM(Bidirectional Long Short-Term Memory 2005)&#xff08;1&#xff09;模型结构说明&#xff08;2&#xff09;创新性说明&#xff08;3&#xff09;示例代码&#xff1a;IMDB电影评论情感分析 …

通义灵码 Visual Studio 下载安装指南(附安装包)

文章目录 前言一、下载和安装指南方法 1&#xff1a;从插件市场安装方法 2&#xff1a;下载安装包安装方法 3&#xff1a;登录并开启智能编码之旅 二、使用指南总结 前言 通义灵码是基于通义大模型的智能编程辅助工具&#xff0c;它提供了多种强大的功能&#xff0c;旨在助力开…

【ProtoBuf】基础使用与编译

文章目录 ProtoBuf的使用基本使用指定proto3语法package声明符定义消息(message)定义消息字段字段唯一编号 编译序列化与反序列化序列化与反序列化使用 ProtoBuf的使用 流程如下&#xff1a; 编写 .proto文件&#xff0c;定义结构对象(message)及属性内容使用 protoc 编译器编…