React中函数式组件与类组件有何不同?

 Function Component 与 Class Component 有何不同 

目录

 Function Component 与 Class Component 有何不同 

文章核心观点:

解释一下:

总结:

文章核心观点:

  1. Function components capture the rendered values.函数式组件捕获的是已经被render的值

解释一下:

请看代码:

Class component

class ProfilePage extends React.Component {showMessage = () => {alert('Followed ' + this.props.user);};handleClick = () => {setTimeout(this.showMessage, 3000);};render() {return <button onClick={this.handleClick}>Follow</button>;}
}

Function Component

function ProfilePage(props) {const showMessage = () => {alert('Followed ' + props.user);};const handleClick = () => {setTimeout(showMessage, 3000);};return (<button onClick={handleClick}>Follow</button>);
}

pjqnl16lm7 - CodeSandbox效果:

LiveDemo

这里有bug:

点击在Sophie的profile的时候,follow这个人,然后在三秒之内快速切换到另一个页面(dan)。Function弹出框的效果是follow sophie,class 弹出框 follow dan。

所以说,function 是我们想要的效果,但是class 不是我们想要的效果。

为什么会出现这种情况呢?

Class Component:

在Class Component中,this.props是通过类的实例来访问的,它指向组件的props。当setTimeout中的this.showMessage函数被调用时,它仍然引用了Class Component的实例,因此它可以访问最新的this.props,这是为什么你看到Class Component中的this.props.user是最新的值的原因。

Function Component:

在Function Component中,props是通过函数的参数传递的。当setTimeout中的showMessage函数被调用时,它只是一个普通的JavaScript函数,没有与Function Component的实例关联,因此它只能访问在函数定义时传递给它的props,而不是最新的props值。

 React 文档中描述的 props 不是不可变(Immutable) 数据吗?什么是不可变数据?

React 中的 props 通常被描述为不可变(immutable)数据,这意味着一旦 props 被传递给组件,它们不应该在组件内部被直接修改。这种不可变性有助于确保组件的可预测性和稳定性,因为它防止了组件在不知情的情况下更改外部传递的数据。

然而,有一点需要注意:props 对象本身是不可变的,但传递给 props 的值可能是可变的。如果你将一个可变对象(例如一个数组或对象)作为 props 传递给组件,那么这个对象的内容可以在组件内部被修改。这并不违反 React 的不可变性原则,因为 React 控制的是 props 对象的不可变性,而不控制传递给 props 的值的不可变性。

function ParentComponent() {const mutableArray = [1, 2, 3];return <ChildComponent items={mutableArray} />;
}

在这种情况下,mutableArray 是一个可变的数组。如果在 ChildComponent 内部修改了 items 数组,它将影响到原始数组。这并不是 React 的 props 不可变性引起的问题,而是因为 JavaScript 中的对象和数组是引用类型。如果你希望在 ChildComponent 中不修改原始数组,可以在内部创建副本来操作数据,以保持原始数据的不可变性。

总之,React 中的 props 本身是不可变的,但你需要注意传递给 props 的值的可变性,特别是当传递引用类型的值时。在组件内部,始终确保遵循不可变性原则,以避免意外的副作用。

有没有办法解决这个问题?

class ProfilePage extends React.Component {render() {// Capture the props!const props = this.props;// Note: we are *inside render*.// These aren't class methods.const showMessage = () => {alert('Followed ' + props.user);};const handleClick = () => {setTimeout(showMessage, 3000);};return <button onClick={handleClick}>Follow</button>;}
}

通过在 render 方法内部创建一个局部变量 props 并将其设置为 this.props 的值,你捕获了初始渲染时的 props 值。这意味着 props 变量将包含初始渲染时传递给组件的值,不受后续渲染的影响。

这种方法有时被用来解决在闭包函数(如 showMessage 和 handleClick 中的函数)中访问最新 props 值的需求。由于在函数内部,props 变量是一个常数(const),所以它将保持对初始 props 值的引用,不会随后的渲染而改变。

那么我想在Function Component中,如何获取到最新的数据?

使用React的useEffect钩子,以依赖props的变化来执行相应的操作。这样,当props更新时,useEffect内的代码会重新运行,确保你获取到最新的props值。

import { useEffect } from 'react';function ProfilePage(props) {useEffect(() => {// 依赖props的变化,当props更新时,这里的代码会重新运行console.log(props);}, [props]);
}

那么在异步的时候,为什么有捕获到初始值的情况?

Function Components是纯函数,它们的行为在某种程度上类似于闭包。当函数组件被创建时,它会捕获当前的作用域(包括props和其他变量)。这意味着在函数组件内部,函数参数(包括props)的值在组件的整个生命周期内保持不变,即使父组件在此期间重新渲染了。

function MyComponent(props) {const someValue = props.someProp;setTimeout(() => {console.log(someValue); // 这里的someValue是在组件初始渲染时捕获的值}, 3000);
}

在这个示例中,someValue 变量在组件初始渲染时捕获了 props.someProp 的值,即使在异步操作中访问 someValue,它仍然保持不变,因为它是在函数作用域内被捕获的。

这就是为什么在Function Component中,在异步操作中可能会访问到初始的props值的原因。如果你希望在异步操作中访问最新的props值,你可以使用React的useEffect Hook来处理副作用,以依赖props的变化来执行相应的操作。这样,当props更新时,useEffect内的代码会重新运行,确保你获取到最新的props值。

总结:

1.class component 使用this 指向可以获取到实例中最新的props值。function component 是个纯函数,相当于闭包,捕获的值就是当前作用域的值。

2.如果function component想获取到最新的值,可以使用hooks,如useEffect,来处理副作用,并在props变化时执行相应的操作,以确保获取到最新的props值。

3.React 中props的不可变性,指的是不要在组件中对它进行修改。所以使用function component纯函数更好,结果值只与参数有关,不会对外部产生副作用。

函数式组件与类组件有何不同? — Overreacted

精读《Function VS Class 组件》 - 掘金 (juejin.cn)

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

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

相关文章

【漏洞复现】深信服科技EDR平台存在任意用户登录漏洞

漏洞描述 深信服终端检测响应平台EDR,通过云网端联动协同、威胁情报共享、多层级响应机制,帮助用户快速处置终端安全问题,构建轻量级、智能化、响应快的下一代终端安全系统。 该EDR系统存在任意用户登录漏洞&#xff0c;攻击者通过漏洞可以登录系统后台并获取服务器的敏感信息…

3D印刷电路板在线渲染查看工具

从概念上讲&#xff0c;这是有道理的&#xff0c;因为PCB印制电路板上的走线从一个连接到下一个连接的路线基本上是平面的。 然而&#xff0c;我们生活在一个 3 维世界中&#xff0c;能够以这种方式可视化电路以及相应的组件&#xff0c;对于设计过程很有帮助。本文将介绍KiCad…

在ubuntu20.04上安装arm-linux-gcc 4.4.3

1下载地址 [http://www.friendlyelec.com.cn/download.asp] 2.将 arm-linux-gcc-4.4.3.tar.gz 拷贝到 /bin目录 无法拷贝怎么办&#xff1f; 出现这种情况是 Linux 拷贝文件时权限不够&#xff0c; 运行命令 sudo nautilus&#xff0c; 打开一个具有管理员权限的文件管理器&am…

微电网的概念

微电网分布式控制理论与方法  顾伟等 微电网的概念和作用 微电网是由多种分布式电源、储能、负载以及相关监控保护装置构成的能够实现自我控制和管理的自治型电力系统&#xff0c;既可以与电网并网进行&#xff0c;也可以以孤岛运行。 分布式发电是指将容量在兆瓦以内的可再…

原生JavaScript+PHP多图上传实现

摘要 很多场景下需要选择多张图片上传&#xff0c;或者是批量上传以提高效率&#xff0c;多图上传的需求自然就比较多了&#xff0c;本文使用最简单的XMLHttpRequest异步上传图片。 界面 上传示例 代码 index.html <!DOCTYPE html> <html><head><titl…

docker 部署vue

1&#xff1a; 首先部署nginx docker run --name nginx -d -p 88:80 nginx 2&#xff1a;访问 http://xxxxxxx:88/ 3: 进入nginx docker exec -it nginx /bin/sh 4: 回到vs&#xff0c;编译项目 npm run build 得到dist文件夹 5&#xff1a;创建docker 6&#xff1a; 将…

蚂蚁发布金融大模型:两大应用产品支小宝2.0、支小助将在完成备案后

9月8日&#xff0c;在上海举办的外滩大会上&#xff0c;蚂蚁集团正式发布金融大模型。据了解&#xff0c;蚂蚁金融大 模型基于蚂蚁自研基础大模型&#xff0c;针对金融产业深度定制&#xff0c;底层算力集群达到万卡规模。该大 模型聚焦真实的金融场景需求&#xff0c;在“认知…

2023 INCLUSION·外滩大会丨拓数派科技战略深度披露,大模型数据计算系统蓄势待发

近日&#xff0c;被亿欧网誉为最值得关注的全球化大模型数据计算科技新锐拓数派亮相在黄浦区世博园举行的2023 INCLUSION外滩大会。作为国际顶尖的科技盛会&#xff0c;来自全球各地的著名经济学家、诺奖得主、企业家和技术大咖们济济一堂&#xff0c;围绕“科技创造可持续未来…

无涯教程-JavaScript - IMLOG10函数

描述 IMLOG10函数以x yi或x yj文本格式返回复数的公共对数(以10为底)。可以从自然对数计算复数的公共对数,如下所示: $$\log_ {10}(x yi)(\log_ {10} e)\ln(x yi)$$ 语法 IMLOG10 (inumber)争论 Argument描述Required/OptionalInumberA complex number for which you …

word文档如何引用参考文献

参考 word文档如何引用参考文献 说明

JavaScript事件处理

表单事件 表单事件在HTML表单中触发 (适用于所有 HTML 元素&#xff0c;但该HTML元素需在form表单内)&#xff1a; 案例演示1&#xff1a;当文本框获取焦点&#xff0c;文本框背景为红色&#xff0c;当文本框失去焦点&#xff0c;文本框背景为黄色 <!DOCTYPE html> <…

C++零碎记录(三)

作者&#xff1a;小王同学在积累 链接&#xff1a;https://www.zhihu.com/question/437657370/answer/1692846096 来源&#xff1a;知乎 著作权归作者所有。商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处。 5. 构造函数和析构函数 5.1 构造函数和析构函数的…

【VR】Network Manager HUD

&#x1f4a6;本专栏是我关于VR开发的笔记 &#x1f236;本篇是——Network Manager HUD Network Manager HUD组件 简介基础知识 简介 网络管理器 HUD是一种快速启动工具&#xff0c;可帮助您立即开始构建多人游戏&#xff0c;而无需首先构建用于游戏创建/连接/加入的用户界面…

SpotBugs代码检查:在整数上进行没有起任何实际作用的位操作(INT_VACUOUS_BIT_OPERATION)

https://spotbugs.readthedocs.io/en/latest/bugDescriptions.html#int-vacuous-bit-mask-operation-on-integer-value-int-vacuous-bit-operation 在整数上进行无用的与、异或操作&#xff0c;实质上没有做任何有用的工作。 例如&#xff1a;v & 0xffffffff 再例如&…

聚观早报|小米14渲染图曝光;蚂蚁金融大模型正式发布

【聚观365】9月9日消息 小米14渲染图曝光 蚂蚁金融大模型正式发布 路特斯推出全电动轿车Emeya 上汽集团8月整车销量42.3万辆 ChatGPT网站流量连续三个月下滑 小米14渲染图曝光 高通旗下全新一代旗舰芯片骁龙8 Gen3将于10月24-26日举办的骁龙技术峰会上亮相&#xff0c;相…

《protobuf》基础语法

文章目录 消息体定义字段规则编译选项实战&#xff1a;编写一个通讯录文件 消息体定义 文件内定义 message Phone {string number 1; }message PeopleInfo {string name 1;int32 age 2;Phone phone 3; }内嵌定义 message PeopleInfo {string name 1;int32 age 2;messa…

Vue3_pinia使用

安装 cnpm install pinia 新建store目录&#xff0c;在store目录下创建loginUser.js import { defineStore } from pinia import {ref} from vue export const userLoginStore defineStore(loginUser, () > {let loginUserInfo ref({})function setUserInfo(data){this.…

Vue中如何实现城市3D分布图

cityfenbu.vue <template><div ><el-card class"seriesmap-box-card"><div slot"header" class"clearfix"><span>城市分布图 (点击可下钻到县)</span></div><div><div class"series-ma…

【科研论文配图绘制】task8 总结与回顾

task8 总结与回顾&#xff0c;这次组队学习大致掌握了常见python绘图工具包的使用&#xff0c;整体上和matlab的语法类似&#xff0c;也是用画布形式控制元素的绘制。印象深刻的是seaborn的使用&#xff0c;在之前做波士顿房价预测时候先接触了seaborn绘制的散点图、直方图和核…

【C++从0到王者】第二十八站:二叉搜索树的应用

文章目录 前言一、Key模型二、Key/Value模型总结 前言 二叉搜索树的在现实世界的应用很广泛&#xff0c;比如Key模型&#xff0c;Key-Value模型就是常见的两种的模型 一、Key模型 K模型&#xff1a;K模型即只有key作为关键码&#xff0c;结构中只需要存储Key即可&#xff0c…