23个react常见问题

1、setState 是异步还是同步?
合成事件中是异步
钩子函数中的是异步
原生事件中是同步
setTimeout中是同步
相关链接:你真的理解setState吗?:

2、聊聊 react@16.4 + 的生命周期
图片
相关连接:React 生命周期 我对 React v16.4 生命周期的理解

3、useEffect(fn, []) 和 componentDidMount 有什么差异?
useEffect 会捕获 props 和 state。所以即便在回调函数里,你拿到的还是初始的 props 和 state。如果想得到“最新”的值,可以使用ref。

4、hooks 为什么不能放在条件判断里?
以 setState 为例,在 react 内部,每个组件(Fiber)的 hooks 都是以链表的形式存在 memoizeState 属性中:

图片
update 阶段,每次调用 setState,链表就会执行 next 向后移动一步。如果将 setState 写在条件判断中,假设条件判断不成立,没有执行里面的 setState 方法,会导致接下来所有的 setState 的取值出现偏移,从而导致异常发生。

参考链接:烤透 React Hook

5、fiber 是什么?
React Fiber 是一种基于浏览器的单线程调度算法。

React Fiber 用类似 requestIdleCallback 的机制来做异步 diff。但是之前数据结构不支持这样的实现异步 diff,于是 React 实现了一个类似链表的数据结构,将原来的 递归diff 变成了现在的 遍历diff,这样就能做到异步可更新了。

图片
相关链接:React Fiber 是什么?

6、聊一聊 diff 算法
传统 diff 算法的时间复杂度是 O(n^3),这在前端 render 中是不可接受的。为了降低时间复杂度,react 的 diff 算法做了一些妥协,放弃了最优解,最终将时间复杂度降低到了 O(n)。

那么 react diff 算法做了哪些妥协呢?,参考如下:

1、tree diff:只对比同一层的 dom 节点,忽略 dom 节点的跨层级移动

如下图,react 只会对相同颜色方框内的 DOM 节点进行比较,即同一个父节点下的所有子节点。当发现节点不存在时,则该节点及其子节点会被完全删除掉,不会用于进一步的比较。

这样只需要对树进行一次遍历,便能完成整个 DOM 树的比较。

图片

这就意味着,如果 dom 节点发生了跨层级移动,react 会删除旧的节点,生成新的节点,而不会复用。

2、component diff:如果不是同一类型的组件,会删除旧的组件,创建新的组件

图片

3、element diff:对于同一层级的一组子节点,需要通过唯一 id 进行来区分

如果没有 id 来进行区分,一旦有插入动作,会导致插入位置之后的列表全部重新渲染。

这也是为什么渲染列表时为什么要使用唯一的 key。

7、调用 setState 之后发生了什么?
在 setState 的时候,React 会为当前节点创建一个 updateQueue 的更新列队。
然后会触发 reconciliation 过程,在这个过程中,会使用名为 Fiber 的调度算法,开始生成新的 Fiber 树, Fiber 算法的最大特点是可以做到异步可中断的执行。
然后 React Scheduler 会根据优先级高低,先执行优先级高的节点,具体是执行 doWork 方法。
在 doWork 方法中,React 会执行一遍 updateQueue 中的方法,以获得新的节点。然后对比新旧节点,为老节点打上 更新、插入、替换 等 Tag。
当前节点 doWork 完成后,会执行 performUnitOfWork 方法获得新节点,然后再重复上面的过程。
当所有节点都 doWork 完成后,会触发 commitRoot 方法,React 进入 commit 阶段。
在 commit 阶段中,React 会根据前面为各个节点打的 Tag,一次性更新整个 dom 元素。
8、为什么虚拟dom 会提高性能?
虚拟dom 相当于在 JS 和真实 dom 中间加了一个缓存,利用 diff 算法避免了没有必要的 dom 操作,从而提高性能。

9、错误边界是什么?它有什么用?
在 React 中,如果任何一个组件发生错误,它将破坏整个组件树,导致整页白屏。这时候我们可以用错误边界优雅地降级处理这些错误。

例如下面封装的组件:

class ErrorBoundary extends React.Component<IProps, IState> {constructor(props: IProps) {super(props);this.state = { hasError: false };}static getDerivedStateFromError() {// 更新 state 使下一次渲染能够显示降级后的 UIreturn { hasError: true };}componentDidCatch(error, errorInfo) {// 可以将错误日志上报给服务器console.log('组件奔溃 Error', error);console.log('组件奔溃 Info', errorInfo);}render() {if (this.state.hasError) {// 你可以自定义降级后的 UI 并渲染return this.props.content;}return this.props.children;}
}

10、什么是 Portals?
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

ReactDOM.createPortal(child, container)

11、React 组件间有那些通信方式?
父组件向子组件通信
1、 通过 props 传递

子组件向父组件通信
1、 主动调用通过 props 传过来的方法,并将想要传递的信息,作为参数,传递到父组件的作用域中

跨层级通信
1、 使用 react 自带的 Context 进行通信,createContext 创建上下文, useContext 使用上下文。

参考下面代码:

import React, { createContext, useContext } from 'react';const themes = {light: {foreground: "#000000",background: "#eeeeee"},dark: {foreground: "#ffffff",background: "#222222"}
};const ThemeContext = createContext(themes.light);function App() {return (<ThemeContext.Provider value={themes.dark}><Toolbar /></ThemeContext.Provider>);
}function Toolbar() {return (<div><ThemedButton /></div>);
}function ThemedButton() {const theme = useContext(ThemeContext);return (<button style={{ background: theme.background, color: theme.foreground }}>I am styled by theme context!</button>);
}export default App;

2、使用 Redux 或者 Mobx 等状态管理库

3、使用订阅发布模式

12、React 父组件如何调用子组件中的方法?
1、如果是在方法组件中调用子组件(>= react@16.8),可以使用 useRef 和 useImperativeHandle:

const { forwardRef, useRef, useImperativeHandle } = React;const Child = forwardRef((props, ref) => {useImperativeHandle(ref, () => ({getAlert() {alert("getAlert from Child");}}));return <h1>Hi</h1>;
});const Parent = () => {const childRef = useRef();return (<div><Child ref={childRef} /><button onClick={() => childRef.current.getAlert()}>Click</button></div>);
};

2、如果是在类组件中调用子组件(>= react@16.4),可以使用 createRef:

const { Component } = React;class Parent extends Component {constructor(props) {super(props);this.child = React.createRef();}onClick = () => {this.child.current.getAlert();};render() {return (<div><Child ref={this.child} /><button onClick={this.onClick}>Click</button></div>);}
}class Child extends Component {getAlert() {alert('getAlert from Child');}render() {return <h1>Hello</h1>;}
}

13、React有哪些优化性能的手段?
类组件中的优化手段
1、使用纯组件 PureComponent 作为基类。

2、使用 React.memo 高阶函数包装组件。

3、使用 shouldComponentUpdate 生命周期函数来自定义渲染逻辑。

方法组件中的优化手段
1、使用 useMemo。

2、使用 useCallBack。

其他方式
1、在列表需要频繁变动时,使用唯一 id 作为 key,而不是数组下标。

2、必要时通过改变 CSS 样式隐藏显示组件,而不是通过条件判断显示隐藏组件。

3、使用 Suspense 和 lazy 进行懒加载,例如:

import React, { lazy, Suspense } from "react";export default class CallingLazyComponents extends React.Component {render() {var ComponentToLazyLoad = null;if (this.props.name == "Mayank") {ComponentToLazyLoad = lazy(() => import("./mayankComponent"));} else if (this.props.name == "Anshul") {ComponentToLazyLoad = lazy(() => import("./anshulComponent"));}return (<div><h1>This is the Base User: {this.state.name}</h1><Suspense fallback={<div>Loading...</div>}><ComponentToLazyLoad /></Suspense></div>)}
}

Suspense 用法可以参考官方文档

相关阅读:21个React性能优化技巧

14、为什么 React 元素有一个 $$typeof 属性?
请添加图片描述

目的是为了防止 XSS 攻击。因为 Synbol 无法被序列化,所以 React 可以通过有没有 $$typeof 属性来断出当前的 element 对象是从数据库来的还是自己生成的。

如果没有 $$typeof 这个属性,react 会拒绝处理该元素。

在 React 的古老版本中,下面的写法会出现 XSS 攻击:

// 服务端允许用户存储 JSON
let expectedTextButGotJSON = {type: 'div',props: {dangerouslySetInnerHTML: {__html: '/* 把你想的搁着 */'},},// ...
};
let message = { text: expectedTextButGotJSON };// React 0.13 中有风险
<p>{message.text}
</p>

15、React 如何区分 Class组件 和 Function组件?
一般的方式是借助 typeof 和 Function.prototype.toString 来判断当前是不是 class,如下:

function isClass(func) {return typeof func === 'function'&& /^class\s/.test(Function.prototype.toString.call(func));
}

但是这个方式有它的局限性,因为如果用了 babel 等转换工具,将 class 写法全部转为 function 写法,上面的判断就会失效。

React 区分 Class组件 和 Function组件的方式很巧妙,由于所有的类组件都要继承 React.Component,所以只要判断原型链上是否有 React.Component 就可以了:

AComponent.prototype instanceof React.Component

16、HTML 和 React 事件处理有什么区别?
在 HTML 中事件名必须小写:

<button onclick='activateLasers()'>

而在 React 中需要遵循驼峰写法:

<button onClick={activateLasers}>

在 HTML 中可以返回 false 以阻止默认的行为:

<a href='#' onclick='console.log("The link was clicked."); return false;' />

而在 React 中必须地明确地调用 preventDefault():

function handleClick(event) {event.preventDefault()console.log('The link was clicked.')
}

17、什么是 suspense 组件?
Suspense 让组件“等待”某个异步操作,直到该异步操作结束即可渲染。在下面例子中,两个组件都会等待异步 API 的返回值:

const resource = fetchProfileData();function ProfilePage() {return (<Suspense fallback={<h1>Loading profile...</h1>}><ProfileDetails /><Suspense fallback={<h1>Loading posts...</h1>}><ProfileTimeline /></Suspense></Suspense>);
}function ProfileDetails() {// 尝试读取用户信息,尽管该数据可能尚未加载const user = resource.user.read();return <h1>{user.name}</h1>;
}function ProfileTimeline() {// 尝试读取博文信息,尽管该部分数据可能尚未加载const posts = resource.posts.read();return (<ul>{posts.map(post => (<li key={post.id}>{post.text}</li>))}</ul>);
}

Suspense 也可以用于懒加载,参考下面的代码:

const OtherComponent = React.lazy(() => import('./OtherComponent'));function MyComponent() {return (<div><Suspense fallback={<div>Loading...</div>}><OtherComponent /></Suspense></div>);
}

18、为什么 JSX 中的组件名要以大写字母开头?
因为 React 要知道当前渲染的是组件还是 HTML 元素。

19、redux 是什么?
Redux 是一个为 JavaScript 应用设计的,可预测的状态容器。

它解决了如下问题:

跨层级组件之间的数据传递变得很容易
所有对状态的改变都需要 dispatch,使得整个数据的改变可追踪,方便排查问题。
但是它也有缺点:

概念偏多,理解起来不容易
样板代码太多
20、react-redux 的实现原理?
通过 redux 和 react context 配合使用,并借助高阶函数,实现了 react-redux。

参考链接:React.js 小书

21、reudx 和 mobx 的区别?
得益于 Mobx 的 observable,使用 mobx 可以做到精准更新;对应的 Redux 是用 dispath 进行广播,通过Provider 和 connect 来比对前后差别控制更新粒度;

相关阅读:Redux or MobX: An attempt to dissolve the Confusion

22、redux 异步中间件有什么什么作用?
假如有这样一个需求:请求数据前要向 Store dispatch 一个 loading 状态,并带上一些信息;请求结束后再向Store dispatch 一个 loaded 状态

一些同学可能会这样做:

function App() {const onClick = () => {dispatch({ type: 'LOADING', message: 'data is loading' })fetch('dataurl').then(() => {dispatch({ type: 'LOADED' })});}return (<div><button onClick={onClick}>click</button></div>);
}

但是如果有非常多的地方用到这块逻辑,那应该怎么办?

聪明的同学会想到可以将 onClick 里的逻辑抽象出来复用,如下:

function fetchData(message: string) {return (dispatch) => {dispatch({ type: 'LOADING', message })setTimeout(() => {dispatch({ type: 'LOADED' })}, 1000)}
}function App() {const onClick = () => {fetchData('data is loading')(dispatch)}return (<div><button onClick={onClick}>click</button></div>);
}

很好,但是 fetchData(‘data is loading’)(dispatch) 这种写法有点奇怪,会增加开发者的心智负担。

于是可以借助 rudux 相关的异步中间件,以 rudux-chunk 为例,将写法改为如下:

function fetchData(message: string) {return (dispatch) => {dispatch({ type: 'LOADING', message })setTimeout(() => {dispatch({ type: 'LOADED' })}, 1000)}
}function App() {const onClick = () => {
-   fetchData('data is loading')(dispatch)
+   dispatch(fetchData('data is loading'))}return (<div><button onClick={onClick}>click</button></div>);
}

这样就更符合认知一些了,redux 异步中间件没有什么奥秘,主要做的就是这样的事情。

相关阅读:Why do we need middleware for async flow in Redux?

23、redux 有哪些异步中间件?
1、redux-thunk

源代码简短优雅,上手简单

2、redux-saga

借助 JS 的 generator 来处理异步,避免了回调的问题

3、redux-observable

借助了 RxJS 流的思想以及其各种强大的操作符,来处理异步问题

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

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

相关文章

【数据结构】栈---C语言版(详解!!!)

文章目录 &#x1f438;一、栈的概念及结构&#x1f344;1、栈的概念定义&#x1f344;2、动图演示&#x1f332;入栈&#x1f332;出栈&#x1f332;整体过程 &#x1f438;二、栈的实现&#x1f438;三、数组结构栈详解&#x1f34e;创建栈的结构⭕接口1&#xff1a;定义结构…

【uniapp/uview】u-datetime-picker 选择器的过滤器用法

引入&#xff1a;要求日期选择的下拉框在分钟显示时&#xff0c;只显示 0 和 30 分钟&#xff1b; <u-datetime-picker :show"dateShow" :filter"timeFilter" confirm"selDateConfirm" cancel"dateCancel" v-model"value1&qu…

yolov5运行过程遇到的小问题(随时更新)

1.关于git的问题 解决办法&#xff1a;插入下面代码 import os os.environ["GIT_PYTHON_REFRESH"] "quiet"2.页面太小无法完成操作 解决办法: 如果不好使再考虑降低Batch_Size大小或者调整虚拟内存可用硬盘空间大小&#xff01;&#xff08;调整虚拟内存…

实现无公网IP的公网环境下Windows远程桌面Ubuntu 18.04连接,高效远程办公!

文章目录 一、 同个局域网内远程桌面Ubuntu1. 更新软件仓库2. 安装支持包3. 安装XFCE4桌面环境4. 安装XRDP5. 环境设置5.1 XFCE桌面配置5.2 在配置文件中&#xff0c;加入XFCE会话 6 重启服务7. 查看IP地址8. 使用Windows远程桌面连接 二、公网环境系统远程桌面Ubuntu1. 注册cp…

【Java】Jxls--轻松生成 Excel

1、介绍 Jxls 是一个小型 Java 库&#xff0c;可以轻松生成 Excel 报告。Jxls 在 Excel 模板中使用特殊标记来定义输出格式和数据布局。 Java 有一些用于创建 Excel 文件的库&#xff0c;例如Apache POI。这些库都很好&#xff0c;但都是一些较底层的库&#xff0c;因为它们要…

【网络安全】图解 Kerberos:身份认证

图解 Kerberos&#xff1a;身份认证 1.什么是 Kerberos &#xff1f;2.Kerberos 基本概念2.1 基本概念2.2 KDC 3.Kerberos 原理3.1 客户端与 Authentication Service3.2 客户端与 Ticket Granting Service3.3 客户端与 HTTP Service Kerberos 是一种身份认证协议&#xff0c;被…

[杂谈]-电动汽车有哪些不同类型

电动汽车有哪些不同类型&#xff1f; 文章目录 电动汽车有哪些不同类型&#xff1f;1、概述2、纯电动汽车&#xff08;BEV&#xff09;3、燃料电池电动汽车&#xff08;FCEV&#xff09;4、插电式混合动力汽车 (PHEV&#xff09;5、混合动力电动汽车 (HEV)6、轻度混合动力HEV7、…

ZooInspector

一、在window&#xff0c;使用我们先打开Zookeeper,目录bin下的zkServer.cmd&#xff0c;把Zookeeper运行起来 ​编辑https://img.111com.net/attachment/art/187687/5f0c25fbe580c.png 二、可以使用目录bin下的zkCli.cmd&#xff0c;查询Zookeeper数据的方式&#xff0c;但是…

【C进阶】分析 C/C++程序的内存开辟与柔性数组(内有干货)

前言&#xff1a; 本文是对于动态内存管理知识后续的补充&#xff0c;以及加深对其的理解。对于动态内存管理涉及的大部分知识在这篇文章中 ---- 【C进阶】 动态内存管理_Dream_Chaser&#xff5e;的博客-CSDN博客 本文涉及的知识内容主要在两方面&#xff1a; 简单解析C/C程序…

基于VueCli创建自定义项目

1.安装脚手架 (已安装) npm i vue/cli -g2.创建项目 vue create hm-exp-mobile选项 Vue CLI v5.0.8 ? Please pick a preset:Default ([Vue 3] babel, eslint)Default ([Vue 2] babel, eslint) > Manually select features 选自定义手动选择功能 选择vue的版本 3.x …

解决在cmd中输入mongo出现‘mongo‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件的问题~

当我想通过shell连接mongoDB时&#xff0c;输入mongo命令&#xff0c;出现下述错误&#xff1a; 起初我以为我是忘记配置环境变量了&#xff0c;但检查后发现自己配置了&#xff0c;如果你和我是一样的问题&#xff0c;明明配置了环境变量&#xff0c;但上述问题依然没有被解决…

Java“牵手”淘宝商品列表数据,关键词搜索淘宝商品数据接口,淘宝API申请指南

淘宝商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取淘宝商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问淘宝商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…

爬虫爬取mp3文件例子

相信训练模型时数据集的获取也是一个很头疼的事情&#xff0c;搞cv领域的可以扛着摄像头架起三脚架拍摄获取&#xff08;以前干过&#xff09;&#xff0c;但是如果是nlp领域的呢&#xff0c;特别是chatgpt等大模型出来后对这类文本等数据的需求更大&#xff0c;如果没有现成的…

Apache实现weblogic集群配置

安装apache&#xff0c;安装相对稳定的版本。如果安装后测试能否正常启动&#xff0c;可以通过访问http://localhost/进行测试。安装Weblogic&#xff0c;参见文档将bea安装目录 weblogic81/server/bin 下的 mod_wl_20.so 文件copy到 apache安装目录下Apache2/modules/目录下A…

联通面试题

一、GC 1.1、目标 GC的主要作用是自动识别和释放不再使用的对象&#xff0c;回收其所占用的内存&#xff0c;以防止内存泄漏和内存溢出的问题。 1.2、如何实现 1.2.1、标记阶段 GC从根对象&#xff08;如线程栈中的引用、静态变量等&#xff09;开始&#xff0c;通过可达性…

构造函数和析构函数(个人学习笔记黑马学习)

构造函数:主要作用在于创建对象时为对象的成员属性赋值&#xff0c;构造函数由编译器自动调用&#xff0c;无须手动调用。析构函数:主要作用在于对象销毁前系统自动调用&#xff0c;执行一些清理工作。 #include <iostream> using namespace std;//对象初始化和清理class…

【MySQL】7、MHA高可用配置及故障切换

MHA概述 MHA&#xff08;Master High Availability&#xff09;是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。 MHA用来解决MySQL单点故障问题&#xff1b; MySQL故障切换过程中&#xff0c;能30秒内自动完成故障切换&#xff0c;并保证数据的一致性&#xff0c;实…

通过wordpress 自定义主题的额外CSS删除指定区块

最近用wordpress建站&#xff0c;想要删除指定区块&#xff0c;发现相关的教程蛮少的&#xff0c;作为小白的我搜了相关教程&#xff0c;好像没找到&#xff0c;只能自己慢慢摸索了&#xff0c;看了很多&#xff0c;终于尝试实现了&#xff0c;特记录下&#xff0c;免得自己忘了…

OceanBase 来参加外滩大会了(内附干货PPT)

9 月 7 日至 9 日&#xff0c;2023 inclusion外滩大会在上海黄浦世博园区举办。8 日&#xff0c;由赛迪顾问与 OceanBase 联合主办的外滩大会“分布式数据库助力数实融合”见解论坛圆满落幕。 数字经济加速发展&#xff0c;数字化转型进入深水区&#xff0c;企业对海量数据的存…

级联H桥储能变流器仿真

1.单个H桥模块的工作状态 2.仿真模型 3.仿真结果 3.1逆变电压网侧电压网侧电流 3.2功率跟踪情况 3.3电流跟踪情况 3.4电池SOC变化曲线 3.5相内SOC均衡效果 3.6相间SOC均衡效果 3.7最大零序电压注入与均衡速度 欢迎同行技术交流&#xff0c;联系方式见置顶文章的底部