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

React - 组件优化、children props 与 render props、错误边界

一、组件优化

1、问题引入
(1)基本介绍
  1. 只要执行 setState,即使不改变状态数据, 组件也会重新 render

  2. 只要当前组件重新 render,就会自动重新 render 子组件,纵使子组件没有用到父组件的任何数据

  3. 只要父组件更新,不管子组件的 props 变没变,子组件都会重新渲染

(2)演示
import { Component } from "react"; import Child from "../Child"; import "./index.css"; export class Parent extends Component { state = { username: "tom", age: 18 }; change = () => { this.setState({ username: this.state.username, age: this.state.age }); }; render() { console.log("Parent 渲染了"); const { username, age } = this.state; return ( <div className="parent"> <h3>Parent</h3> <div>username: {username}</div> <div>age: {age}</div> <button onClick={this.change}>点我修改</button> <Child /> </div> ); } }
.parent{width:500px;background-color:orange;padding:8px;}
import { Component } from "react"; import "./index.css"; export default class Child extends Component { render() { console.log("Child 渲染了"); return ( <div className="child"> <h3>Child</h3> </div> ); } }
.child{width:100%;background-color:skyblue;padding:8px;}
  1. 首次渲染,输出结果如下
Parent 渲染了 Child 渲染了
  1. 第 1 次点击【点我修改】按钮,输出结果如下
Parent 渲染了 Child 渲染了
  1. 第 2 次点击【点我修改】按钮,输出结果如下
Parent 渲染了 Child 渲染了
2、问题原因
  • Component 中的 shouldComponentUpdate 方法总是返回 true
3、处理策略
  1. 重写 shouldComponentUpdate 方法,比较新旧 state 或 props 数据,如果有变化则返回 true,没有则返回 false
import { Component } from "react"; import Child from "../Child"; import "./index.css"; export class Parent extends Component { state = { username: "tom", age: 18 }; change = () => { this.setState({ username: this.state.username }); }; shouldComponentUpdate(nextProps, nextState) { // nextProps 是接下来要变化的目标 props // nextState 是接下来要变化的目标 state return nextState.username !== this.state.username || nextState.age !== this.state.age; } render() { console.log("Parent 渲染了"); const { username, age } = this.state; return ( <div className="parent"> <h3>Parent</h3> <div>username: {username}</div> <div>age: {age}</div> <button onClick={this.change}>点我修改</button> <Child /> </div> ); } }
  1. 使用 PureComponent,它重写了 shouldComponentUpdate 方法,只有 state 或 props 数据有变化才返回 true
import { PureComponent } from "react"; import Child from "../Child"; import "./index.css"; export class Parent extends PureComponent { state = { username: "tom", age: 18 }; change = () => { this.setState({ username: this.state.username }); }; render() { console.log("Parent 渲染了"); const { username, age } = this.state; return ( <div className="parent"> <h3>Parent</h3> <div>username: {username}</div> <div>age: {age}</div> <button onClick={this.change}>点我修改</button> <Child /> </div> ); } }
4、注意事项
(1)基本介绍
  1. PureComponent 只是进行 state 和 props 数据的浅比较,如果是数据对象内部数据变了,返回 false

  2. 不要直接修改 state 数据,而是要产生新数据

(2)演示
import { PureComponent } from "react"; import Child from "../Child"; import "./index.css"; export class Parent extends PureComponent { state = { person: { username: "tom", age: 18, }, }; // 这里改变了第 1 层 change1 = () => { this.setState({ person: { ...this.state.person } }); }; // 这里改变了第 2 层,没有改变第 1 层 change2 = () => { const { person } = this.state; person.username = "jerry"; person.age = 20; this.setState({ person: person }); }; render() { console.log("Parent 渲染了"); const { username, age } = this.state.person; return ( <div className="parent"> <h3>Parent</h3> <div>username: {username}</div> <div>age: {age}</div> <button onClick={this.change1}>点我修改 1</button> <button onClick={this.change2}>点我修改 2</button> <Child /> </div> ); } }
.parent{width:500px;background-color:orange;padding:8px;}
import { Component } from "react"; import "./index.css"; export default class Child extends Component { render() { console.log("Child 渲染了"); return ( <div className="child"> <h3>Child</h3> </div> ); } }
.child{width:100%;background-color:skyblue;padding:8px;}
  1. 首次渲染,输出结果如下
Parent 渲染了 Child 渲染了
  1. 第 1 次点击【点我修改 1】按钮,输出结果如下
Parent 渲染了 Child 渲染了
  1. 第 2 次点击【点我修改 2】按钮,输出结果如下
Parent 渲染了 Child 渲染了
  1. 第 1 次点击【点我修改 2】按钮,输出结果如下
(无)
  1. 第 2 次点击【点我修改 2】按钮,输出结果如下
(无)

二、children props 与 render props

1、基本介绍
  1. children props 是通过组件标签体的方式向组件内部传递内容

  2. 在组件内部,可以通过props.children来获取这些内容

  3. 但是,如果内容需要父组件内部的数据,children props 做不到,需要使用 render props 来实现

2、演示
(1)children props
export default function Card(props) { return ( <> <h3>Card</h3> {props.children} </> ); }
import Card from "./components/Card"; export default function App() { return ( <> <Card> <p>这是卡片内部的内容</p> <button>点击按钮</button> </Card> </> ); }
(2)render props
import { useState } from "react"; export default function Card(props) { const [content] = useState("这是一段测试内容"); return ( <> <h3>Card</h3> {props.render(content)} </> ); }
export default function CardInner(props) { return ( <> <p>这是卡片内部的内容</p> <button>点击按钮</button> <div>{props.content}</div> </> ); }
import Card from "./components/Card"; import CardInner from "./components/CardInner"; export default function App() { return ( <> <Card render={(content) => <CardInner content={content} />} /> </> ); }

三、错误边界

1、基本介绍
  1. 错误边界(Error Boundary)用来捕获后代组件错误,渲染出备用页面

  2. 只能捕获后代组件生命周期产生的错误,不能捕获自己组件产生的错误,以及其他组件在合成事件、定时器中产生的错误

2、演示
import { PureComponent } from "react"; import Child from "../Child"; import "./index.css"; export class Parent extends PureComponent { state = { hasError: "", }; static getDerivedStateFromError(error) { console.log("@@@", error); return { hasError: error }; } componentDidCatch(error, info) { console.log("此处统计错误,反馈给服务"); console.log(error, info); } render() { return ( <div className="parent"> <h3>Parent</h3> {this.state.hasError ? <h3>当前网络不稳定,稍后再试</h3> : <Child />} </div> ); } }
.parent{width:500px;background-color:orange;padding:8px;}
import { Component } from "react"; import "./index.css"; export default class Child extends Component { // state = { // users: [ // { id: "001", name: "tom", age: 18 }, // { id: "002", name: "jack", age: 19 }, // { id: "003", name: "merry", age: 20 }, // ], // }; // 模拟一个错误 state = { users: "test", }; render() { return ( <div className="child"> <h3>Child</h3> {this.state.users.map((userObj) => { return ( <div key={userObj.id}> {userObj.name} ----- {userObj.age} </div> ); })} </div> ); } }
.child{width:100%;background-color:skyblue;padding:8px;}
http://www.jsqmd.com/news/614384/

相关文章:

  • Windows 11终极优化指南:使用Win11Debloat实现系统性能提升
  • 如何快速将B站m4s缓存视频转换为MP4:终极转换工具使用指南
  • ROS2结合cartographer实现高精度激光SLAM建图实战
  • TALL预设与Laravel Jetstream对比:哪个更适合你的项目?
  • Goqu高级查询技巧:窗口函数、子查询、复杂JOIN实战指南
  • 从AlphaFold到GPT:AI for Science大模型技术演进全解析 [特殊字符]
  • 万字拆解 LLM 运行机制:Token、上下文与采样参数举
  • 台达AS系列PLC的Modbus TCP通信C#源代码及生产数据监控与Excel表格生成
  • 揭秘PoeCharm:如何用精准数据构建《流放之路》完美角色?
  • Simditor自定义配置进阶:掌握allowedTags、allowedAttributes等高级选项的终极指南
  • P8087 『JROI-5』Interval 题解
  • PyTorch 张量与自动微分完全指南:从核心概念到实战训练
  • 小白的第一次edusrc挖洞经历分享
  • 掌握nvim-tree.lua正则表达式:5个高级文件过滤技巧让你的Neovim文件管理效率翻倍
  • 如何通过MiPad5-Drivers开源驱动实现跨系统适配?设备转型与性能优化指南
  • Apollo GraphQL完全指南:从零开始构建现代化应用
  • FanControl智能配置指南:从噪音困扰到散热大师的转型方案
  • 2026年4月二合一粘结测定仪公司推荐,实测表现大揭秘,高精度微机全自动量热仪/全自动测硫仪,测定仪源头厂家推荐 - 品牌推荐师
  • NorthwindTraders缓存优化终极指南:Redis vs 内存缓存性能大比拼
  • ffmpeg转换格式
  • AlertKit完全指南:如何在iOS应用中实现Apple原生风格弹窗
  • 如何高效管理全面战争MOD:虎符台/Legion Seal终极指南
  • 从xcode-install到xcodes:项目迁移指南与版本管理工具演进
  • RPG Maker解密工具终极指南:快速提取游戏资源与素材
  • Simditor插件开发终极指南:如何快速创建自定义按钮和功能
  • PHP网关TLS1.3握手失败率高达37%?实测对比BoringSSL vs OpenSSL 3.0.12在PLC通信网关中的握手兼容性矩阵
  • Onyx:开源AI平台,让每个团队都能拥有强大AI助手
  • 五分钟快速上手PPTist:打造专业级在线演示文稿的终极指南
  • 第三次作业 网络嗅探与协议分析
  • DeepTutor智能复习系统:基于遗忘曲线的高效复习策略终极指南