位置: IT常识 - 正文

2023版最新最全React面试题

编辑:rootadmin
2023版最新最全React面试题

推荐整理分享2023版最新最全React面试题,希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:,内容如对您有帮助,希望把文章链接给更多的朋友!

React 作为前端使用最多的框架,必然是面试的重点。我们接下来主要从 React 的使用方式、源码层面和周边生态(如 redux, react-router 等)等几个方便来进行总结。

1. 使用方式上

这里主要考察的是,在开发使用过程中,对 React 框架的了解,如 hook 的不同调用方式得到的结果、函数组件中的 useState 和类组件的 state 的区别等等。

props 的变动,是否会引起 state hook 中数据的变动?

React 组件的 props 变动,会让组件重新执行,但并不会引起 state 的值的变动。state 值的变动,只能由 setState() 来触发。因此若想在 props 变动时,重置 state 的数据,需要监听 props 的变动,如:

const App = props => { const [count, setCount] = useState(0); // 监听 props 的变化,重置 count 的值 useEffect(() => { setCount(0); }, [props]); return <div onClick={() => setCount(count + 1)}>{count}</div>;};React18 有哪些新变化?

React 的更新都是渐进式的更新,在 React18 中启用的新特性,其实在 v17 中(甚至更早)就埋下了。

并发渲染机制:根据用户的设备性能和网速对渲染过程进行适当的调整, 保证 React 应用在长时间的渲染过程中依旧保持可交互性,避免页面出现卡顿或无响应的情况,从而提升用户体验。新的创建方式:现在是要先通过createRoot()创建一个 root 节点,然后该 root 节点来调用render()方法;自动批处理优化:批处理: React 将多个状态更新分组到一个重新渲染中以获得更好的性能。(将多次 setstate 事件合并);在 v18 之前只在事件处理函数中实现了批处理,在 v18 中所有更新都将自动批处理,包括 promise 链、setTimeout 等异步代码以及原生事件处理函数;startTransition:主动降低优先级。比如「搜索引擎的关键词联想」,用户在输入框中的输入希望是实时的,而联想词汇可以稍稍延迟一会儿。我们可以用 startTransition 来降低联想词汇更新的优先级;useId:主要用于 SSR 服务端渲染的场景,方便在服务端渲染和客户端渲染时,产生唯一的 id;并发模式是如何执行的?

React 中的并发,并不是指同一时刻同时在做多件事情。因为 js 本身就是单线程的(同一时间只能执行一件事情),而且还要跟 UI 渲染竞争主线程。若一个很耗时的任务占据了线程,那么后续的执行内容都会被阻塞。为了避免这种情况,React 就利用 fiber 结构和时间切片的机制,将一个大任务分解成多个小任务,然后按照任务的优先级和线程的占用情况,对任务进行调度。

对于每个更新,为其分配一个优先级 lane,用于区分其紧急程度。通过 Fiber 结构将不紧急的更新拆分成多段更新,并通过宏任务的方式将其合理分配到浏览器的帧当中。这样就能使得紧急任务能够插入进来。高优先级的更新会打断低优先级的更新,等高优先级更新完成后,再开始低优先级更新。什么是受控组件和非受控组件?

我们稍微了解下什么是受控组件和非受控组件:

受控组件:只能通过 React 修改数据或状态的组件,就是受控组件;非受控组件:与受控组件相反,如 input, textarea, select, checkbox 等组件,本身控件自己就能控制数据和状态的变更,而且 React 是不知道这些变更的;

那么如何将非受控组件改为受控组件呢?那就是把上面的这些纯 html 组件数据或状态的变更,交给 React 来操作:

const App = () => { const [value, setValue] = useState(''); const [checked, setChecked] = useState(false); return ( <> <input value={value} onInput={event => setValue(event.target.value)} /> <input type="checkbox" checked={checked} onChange={event => setChecked(event.target.checked)} /> </> );};

上面代码中,输入框和 checkbox 的变化,均是经过了 React 来操作的,在数据变更时,React 是能够知道的。

高阶组件(HOC)?高阶组件?

高阶组件通过包裹(wrapped)被传入的 React 组件,经过一系列处理,最终返回一个相对增强(enhanced)的 React 组件,供其他组件调用。

作用:

复用逻辑:高阶组件更像是一个加工 react 组件的工厂,批量对原有组件进行加工,包装处理。我们可以根据业务需求定制化专属的 HOC,这样可以解决复用逻辑。强化 props:这个是 HOC 最常用的用法之一,高阶组件返回的组件,可以劫持上一层传过来的 props,然后混入新的 props,来增强组件的功能。代表作 react-router 中的 withRouter。赋能组件:HOC 有一项独特的特性,就是可以给被 HOC 包裹的业务组件,提供一些拓展功能,比如说额外的生命周期,额外的事件,但是这种 HOC,可能需要和业务组件紧密结合。典型案例 react-keepalive-router 中的 keepaliveLifeCycle 就是通过 HOC 方式,给业务组件增加了额外的生命周期。控制渲染:劫持渲染是 hoc 一个特性,在 wrapComponent 包装组件中,可以对原来的组件,进行条件渲染,节流渲染,懒加载等功能,后面会详细讲解,典型代表做 react-redux 中 connect 和 dva 中 dynamic 组件懒加载。

参考:react 进阶」一文吃透 React 高阶组件(HOC)

React 中为什么要使用 Hook?

官方网站有介绍该原因:使用 Hook 的动机。

这里我们简要的提炼下:

在组件之间复用状态逻辑很难:在类组件中,可能需要 render props 和 高阶组件等方式,但会形成“嵌套地域”;而使用 Hook,则可以从组件中提取状态逻辑,是的这些逻辑可以单独测试并复用;复杂组件变得难以理解:在类组件中,每个生命周期常常包含一些不相关的逻辑。如不同的执行逻辑,都要放在componentDidMount中执行和获取数据,而之后需在 componentWillUnmount 中清除;但在函数组件中,不同的逻辑可以放在不同的 Hook 中执行,互不干扰;难以理解的 class:类组件中,充斥着各种对 this 的使用,如 this.onClick.bind(this),this.state,this.setState() 等,同时,class 不能很好的压缩,并且会使热重载出现不稳定的情况;Hook 使你在非 class 的情况下可以使用更多的 React 特性;useCallback 和 useMemo 的使用场景

useCallback 和 useMemo 可以用来缓存函数和变量,提高性能,减少资源浪费。但并不是所有的函数和变量都需要用这两者来实现,他也有对应的使用场景。

我们知道 useCallback 可以缓存函数体,在依赖项没有变化时,前后两次渲染时,使用的函数体是一样的。它的使用场景是:

函数作为其他 hook 的依赖项时(如在 useEffect()中);函数作为 React.memo()(或 shouldComponentUpdate )中的组件的 props;

主要是为了避免重新生成的函数,会导致其他 hook 或组件的不必要刷新。

useMemo 用来缓存函数执行的结果。如每次渲染时都要执行一段很复杂的运算,或者一个变量需要依赖另一个变量的运算结果,就都可以使用 useMemo()。

参考文章:React18 源码解析之 useCallback 和 useMemo。

useState 的传参方式,有什么区别?

useState()的传参有两种方式:纯数据和回调函数。这两者在初始化时,除了传入方式不同,没啥区别。但在调用时,不同的调用方式和所在环境,输出的结果也是不一样的。

如:

const App = () => { const [count, setCount] = useState(0); const handleParamClick = () => { setCount(count + 1); setCount(count + 1); setCount(count + 1); }; const handleCbClick = () => { setCount(count => count + 1); setCount(count => count + 1); setCount(count => count + 1); };};

上面的两种传入方式,最后得到的 count 结果是不一样的。为什么呢?因为在以数据的格式传参时,这 3 个使用的是同一个 count 变量,数值是一样的。相当于setCount(0 + 1),调用了 3 次;但以回调函数的传参方式,React 则一般地会直接该回调函数,然后得到最新结果并存储到 React 内部,下次使用时就是最新的了。注意:这个最新值是保存在 React 内部的,外部的 count 并不会马上更新,只有在下次渲染后才会更新。

还有,在定时器中,两者得到的结果也是不一样的:

const App = () => { const [count, setCount] = useState(0); useEffect(() => { const timer = setInterval(() => { setCount(count + 1); }, 500); return () => clearInterval(timer); }, []); useEffect(() => { const timer = setInterval(() => { setCount(count => count + 1); }, 500); return () => clearInterval(timer); }, []);};为什么在本地开发时,组件会渲染两次?2023版最新最全React面试题

issues#2

在 React.StrictMode 模式下,如果用了 useState,usesMemo,useReducer 之类的 Hook,React 会故意渲染两次,为的就是将一些不容易发现的错误容易暴露出来,同时 React.StrictMode 在正式环境中不会重复渲染。

也就是在测试环境的严格模式下,才会渲染两次。

如何实现组件的懒加载

从 16.6.0 开始,React 提供了 lazy 和 Suspense 来实现懒加载。

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

属性fallback表示在加载组件前,渲染的内容。

如何实现一个定时器的 hook

若在定时器内直接使用 React 的代码,可能会收到意想不到的结果。如我们想实现一个每 1 秒加 1 的定时器:

const App = () => { const [count, setCount] = useState(0); useEffect(() => { const timer = setInterval(() => { setCount(count + 1); }, 1000); return () => clearInterval(timer); }, []); return <div className="App">{count}</div>;};

可以看到,coun 从 0 变成 1 以后,就再也不变了。为什么会这样?

尽管由于定时器的存在,组件始终会一直重新渲染,但定时器的回调函数是挂载期间定义的,所以它的闭包永远是对挂载时 Counter 作用域的引用,故 count 永远不会超过 1。

针对这个单一的 hook 调用,还比较好解决,例如可以监听 count 的变化,或者通过 useState 的 callback 传参方式。

const App = () => { const [count, setCount] = useState(0); // 监听 count 的变化,不过这里将定时器改成了 setTimeout // 即使不修改,setInterval()的timer也会在每次渲染时被清除掉, // 然后重新启动一个新的定时器 useEffect(() => { const timer = setTimeout(() => { setCount(count + 1); }, 1000); return () => clearInterval(timer); }, [count]); // 以回调的方式 // 回调的方式,会计算回调的结果,然后作为下次更新的初始值 // 详情可见: https://www.xiabingbao.com/post/react/react-usestate-rn5bc0.html#5.+updateReducer useEffect(() => { const timer = setInterval(() => { setCount(count => count + 1); }, 1000); return () => clearInterval(timer); }, []); return <div className="App">{count}</div>;};

当然还有别的方式也可以实现 count 的更新。那要是调用更多的 hook,或者更复杂的代码,该怎么办呢?这里我们可以封装一个新的 hook 来使用:

// https://overreacted.io/zh-hans/making-setinterval-declarative-with-react-hooks/const useInterval = (callback: () => void, delay: number | null): void => { const savedCallback = useRef(callback); useEffect(() => { savedCallback.current = callback; }); useEffect(() => { function tick() { savedCallback.current(); } if (delay !== null) { const id = setInterval(tick, delay); return () => clearInterval(id); } }, [delay]);};useEffect()的清除机制是什么?在什么时候执行?

useEffect(callback)的回调函数里,若有返回的函数,这是 effect 可选的清除机制。每个 effect 都可以返回一个清除函数。

React 何时清除 effect? React 会在组件卸载的时候执行清除操作。同时,若组件产生了更新,会先执行上一个的清除函数,然后再运行下一个 effect。如

// 运行第一个 effect// 产生更新时// 清除上一个 effect// 运行下一个 effect// 产生更新时// 清除上一个 effect// 运行下一个 effect// 组件卸载时// 清除最后一个 effect

参考:为什么每次更新的时候都要运行 Effect

2. 源码层面上

这部分考察的就更有深度一些了,多多少少得了解一些源码,才能明白其中的缘由,比如 React 的 diff 对比,循环中 key 的作用等。

虚拟 dom 有什么优点?真实 dom 和虚拟 dom,谁快?

Virtual DOM 是以对象的方式来描述真实 dom 对象的,那么在做一些 update 的时候,可以在内存中进行数据比对,减少对真实 dom 的操作减少浏览器重排重绘的次数,减少浏览器的压力,提高程序的性能,并且因为 diff 算法的差异比较,记录了差异部分,那么在开发中就会帮助程序员减少对差异部分心智负担,提高了开发效率。

虚拟 dom 好多这么多,渲染速度上是不是比直接操作真实 dom 快呢?并不是。虚拟 dom 增加了一层内存运算,然后才操作真实 dom,将数据渲染到页面上。渲染上肯定会慢上一些。虽然虚拟 dom 的缺点在初始化时增加了内存运算,增加了首页的渲染时间,但是运算时间是以毫秒级别或微秒级别算出的,对用户体验影响并不是很大。

什么是合成事件,与原生事件有什么区别?

React 中所有触发的事件,都是自己在其内部封装了一套事件机制。目的是为了实现全浏览器的一致性,抹平不同浏览器之间的差异性。

在 React17 之前,React 是把事件委托在 document 上的,React17 及以后版本不再把事件委托在 document 上,而是委托在挂载的容器上。React 合成事件采用的是事件冒泡机制,当在某具体元素上触发事件时,等冒泡到顶部被挂载事件的那个元素时,才会真正地执行事件。

而原生事件,当某具体元素触发事件时,会立刻执行该事件。因此若要比较事件触发的先后时机时,原生事件会先执行,React 合成事件会后执行。

key 的作用是什么?

key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识。

当组件刷新时,React 内部会根据 key 和元素的 type,来对比元素是否发生了变化。若选做 key 的数据有问题,可能会在更新的过程中产生异常。

参考:React18 源码解析之 key 的作用。

多次执行 useState(),会触发多次更新吗?

在 React18 中,无论是多个 useState()的 hook,还是操作(dispatch)多次的数据。只要他们在同一优先级,React 就会将他们合并到一起操作,最后再更新数据。

这是基于 React18 的批处理机制。React 将多个状态更新分组到一个重新渲染中以获得更好的性能。(将多次 setstate 事件合并);在 v18 之前只在事件处理函数中实现了批处理,在 v18 中所有更新都将自动批处理,包括 promise 链、setTimeout 等异步代码以及原生事件处理函数;

参考:多次调用 useState() 中的 dispatch 方法,会产生多次渲染吗?

useState()的 state 是否可以直接修改?是否可以引起组件渲染?

首先

本文链接地址:https://www.jiuchutong.com/zhishi/300232.html 转载请保留说明!

上一篇:【GitHub Copilot X】基于GPT-4的全新智能编程助手

下一篇:midjourney 初级使用说明

  • 苹果手机怎么图片识别文字(苹果手机怎么图片编辑)

    苹果手机怎么图片识别文字(苹果手机怎么图片编辑)

  • 小米手机怎么滚动截屏(小米手机怎么滚动截屏长图)

    小米手机怎么滚动截屏(小米手机怎么滚动截屏长图)

  • 拼多多详情页尺寸多少(拼多多详情页尺寸多少像素)

    拼多多详情页尺寸多少(拼多多详情页尺寸多少像素)

  • 荣耀10录屏功能在哪里(荣耀10录屏功能怎么开启)

    荣耀10录屏功能在哪里(荣耀10录屏功能怎么开启)

  • 微信注销后聊天记录还在吗(微信重新登录后聊天记录没了)

    微信注销后聊天记录还在吗(微信重新登录后聊天记录没了)

  • plc的软件系统可分为哪两大部分(plc的软件系统可分为应用软件)

    plc的软件系统可分为哪两大部分(plc的软件系统可分为应用软件)

  • 闲鱼未拆封机怎么验货(闲鱼未拆封机可信吗)

    闲鱼未拆封机怎么验货(闲鱼未拆封机可信吗)

  • 抖音取关一个人她会知道么(抖音取关一个人还会刷到吗)

    抖音取关一个人她会知道么(抖音取关一个人还会刷到吗)

  • 怎么知道抖音作品有没有上热门(怎么知道抖音作品有没有被限流)

    怎么知道抖音作品有没有上热门(怎么知道抖音作品有没有被限流)

  • opj文件用什么软件打开(op文件是什么)

    opj文件用什么软件打开(op文件是什么)

  • 应用锁正在保护什么意思(应用锁正在保护通知怎么关闭)

    应用锁正在保护什么意思(应用锁正在保护通知怎么关闭)

  • 荣耀9x像素多少万(荣耀magic5pro像素)

    荣耀9x像素多少万(荣耀magic5pro像素)

  • 制冷片原理(制冷片原理材料)

    制冷片原理(制冷片原理材料)

  • 微信字体是什么字体(微信字体是什么字号)

    微信字体是什么字体(微信字体是什么字号)

  • 系统压缩有什么坏处(系统压缩文件)

    系统压缩有什么坏处(系统压缩文件)

  • 台式电脑放太久开不了机(台式电脑放太久开不了机,亮了一下)

    台式电脑放太久开不了机(台式电脑放太久开不了机,亮了一下)

  • 碎屏险包括内屏吗(碎屏险包不包内屏)

    碎屏险包括内屏吗(碎屏险包不包内屏)

  • 华为mate30怎么导出联系人(华为mate30怎么导入旧手机数据)

    华为mate30怎么导出联系人(华为mate30怎么导入旧手机数据)

  • 超级取景框怎么用(超级取景框怎么关闭)

    超级取景框怎么用(超级取景框怎么关闭)

  • ie浏览器改成兼容模式(ie浏览器改成兼容怎么改)

    ie浏览器改成兼容模式(ie浏览器改成兼容怎么改)

  • 电池开票属于哪类别(电池开票属于哪类编码)

    电池开票属于哪类别(电池开票属于哪类编码)

  • 豆瓣话题从哪里进(豆瓣话题怎么看)

    豆瓣话题从哪里进(豆瓣话题怎么看)

  • 手机照片分辨率怎么调(苹果手机照片分辨率)

    手机照片分辨率怎么调(苹果手机照片分辨率)

  • 支付宝宝盒怎么连蓝牙(支付宝宝盒怎么领取)

    支付宝宝盒怎么连蓝牙(支付宝宝盒怎么领取)

  • 怎么关闭qq头像分享(怎么关闭qq头像同步到空间)

    怎么关闭qq头像分享(怎么关闭qq头像同步到空间)

  • 华为p30pro屏幕摔坏怎么办(华为p30pro屏幕摔碎图片)

    华为p30pro屏幕摔坏怎么办(华为p30pro屏幕摔碎图片)

  • 对方微信朋友圈一条线(对方微信朋友圈一条横线中间一个点是什么意思)

    对方微信朋友圈一条线(对方微信朋友圈一条横线中间一个点是什么意思)

  • 关闭Edge Dev浏览器新建标签页下方的资讯内容(新版关闭edge地址栏建议)

    关闭Edge Dev浏览器新建标签页下方的资讯内容(新版关闭edge地址栏建议)

  • yolov5画框重复、大框包小框问题解决,c++、python代码调用onnx

    yolov5画框重复、大框包小框问题解决,c++、python代码调用onnx

  • 展现AI与自动化测试技术之间的神奇化学反应(ai与自动化有什么区别)

    展现AI与自动化测试技术之间的神奇化学反应(ai与自动化有什么区别)

  • 增值税专用发票使用规定 最新
  • 一次性收取加盟费 所得税
  • 长期借调人员差旅费是谁的责任
  • 发票打印机贵吗
  • 国内旅客运输服务电子普通发票
  • 公司账外现金
  • 新开商贸公司怎么做账和报税
  • 石油天然气管道保护法
  • 企业所得税前扣除是啥意思
  • 企业如何申请科研项目
  • 企业办自建厂房理房产证需要什么资料
  • 来料加工企业的会计处理问题
  • 年终奖个税公式表最新
  • 红字发票信息表是销方还是购方开
  • 以旧翻新视频
  • 独立核算分公司可以享受小型微利企业优惠吗
  • 收到保险返利计入什么
  • 预收的销售商品货款通过什么科目核算
  • 当月认证下月抵扣
  • 公司给员工发工资用途怎么写
  • 会议费 报销
  • 其他综合收益的含义
  • 收到返还代扣代缴手续费如何入账?
  • 本期应付而未付工资挂账处理?
  • 在win7中,打开资源管理器的快捷键
  • win10双系统修改名称
  • 关于怀孕在线咨询
  • service5.exe - service5是什么进程 有什么用
  • 公司收到个人入股资金要交税吗
  • 腾达ac9路由器怎么样
  • zmweb.exe是什么进程
  • mmc.exe是什么进程
  • windows7旗舰版最新版本
  • 以非现金资产清偿债务的,债权人应当
  • 外汇差额核销条件
  • php的项目
  • 子公司破产对母公司是利好还是利空
  • vscode2010下载
  • 卷积神经网络CNN实验报告
  • 大模型时代的自然语言处理
  • html span标签作用
  • 自产产品用于福利账务处理
  • 未开票要交增值税吗
  • 支付贷款利息属于筹资活动吗
  • 物业合并利润表怎么填
  • 门禁卡一般属于什么卡
  • access speed
  • 国税发1997191号文有效吗
  • 工程结算与工程施工
  • 银行承兑汇票利息归谁
  • 日记账对方科目代表什么意思
  • 日记账是否必须全部建立
  • 账簿凭证的管理要求
  • sql server使用sql语句
  • sql server数据库查询语句
  • Vista系统提高ADSL上网速度的两种设置方法
  • windowsserver2008远程桌面怎么打开
  • linux系统怎么安装
  • 在windowsxp的应用程序中,经常有一些菜单选项呈暗灰色
  • windows8鼠标点击右键反应慢咋回事
  • window7系统中的桌面指什么
  • Win7旗舰版系统镜像文件
  • ubuntu14.04.6安装教程
  • win7系统中怎么查看隐藏文件
  • 逐一介绍班子成员表现
  • 安卓图库权限
  • 深入理解python特性 pdf
  • Shell脚本中不同进制数据转换的例子(二进制、八进制、十六进制、base64)
  • js瀑布流布局
  • jquery 添加
  • android网络开发技术答案形考任务五
  • jquery keydown
  • java面向对象和Java有区别吗
  • python convexhull
  • 生产者消费者的作用
  • 淄博市地税局局长
  • 简述会计估计及其特点
  • 如何做好税务党建工作
  • 福建福州有几个火车站
  • 湖北退役士兵退伍费
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设