位置: 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 初级使用说明

  • 在京东慧采平台怎么入驻(在京东慧采平台采购的单位)

    在京东慧采平台怎么入驻(在京东慧采平台采购的单位)

  • 苹果13激活一定要插卡吗(苹果13激活要半个小时吗)

    苹果13激活一定要插卡吗(苹果13激活要半个小时吗)

  • oppofindx2pro能支持杜比全景声吗(oppofindx2pro支持nfc吗)

    oppofindx2pro能支持杜比全景声吗(oppofindx2pro支持nfc吗)

  • 华为matebookd14能用ps吗(华为matebookD14能玩英雄联盟吗)

    华为matebookd14能用ps吗(华为matebookD14能玩英雄联盟吗)

  • 华为荣耀20i充电速度快吗(华为荣耀20i充电口是什么样的)

    华为荣耀20i充电速度快吗(华为荣耀20i充电口是什么样的)

  • 怎么查找已经刷过的抖音视频(怎么查找已经刷过的抖音直播视频)

    怎么查找已经刷过的抖音视频(怎么查找已经刷过的抖音直播视频)

  • 单片机应用系统是由什么组成的(单片机应用系统的设计原则)

    单片机应用系统是由什么组成的(单片机应用系统的设计原则)

  • t106平板电脑是什么牌子(平板t110)

    t106平板电脑是什么牌子(平板t110)

  • qq邮箱发视频没有声音(qq邮箱发的视频为什么没有声音)

    qq邮箱发视频没有声音(qq邮箱发的视频为什么没有声音)

  • 抖音直播房间封禁是怎么回事(抖音直播房间封禁是什么意思)

    抖音直播房间封禁是怎么回事(抖音直播房间封禁是什么意思)

  • 苹果手机语音发不出去是什么原因(苹果手机语音发不出去系统错误)

    苹果手机语音发不出去是什么原因(苹果手机语音发不出去系统错误)

  • 抖音能看到谁点赞吗(抖音能看到谁点赞后取消)

    抖音能看到谁点赞吗(抖音能看到谁点赞后取消)

  • 微信下载后安装不上怎么办(微信下载后安装失败)

    微信下载后安装不上怎么办(微信下载后安装失败)

  • 怎么发送文档(怎么发送文档到别人邮箱)

    怎么发送文档(怎么发送文档到别人邮箱)

  • ipad120刷新率有哪些设备(刷新率120的ipad)

    ipad120刷新率有哪些设备(刷新率120的ipad)

  • 苹果待退款什么时候到账(ios待退款)

    苹果待退款什么时候到账(ios待退款)

  • m1805e2a是小米什么型号(小米m1805e2a价格)

    m1805e2a是小米什么型号(小米m1805e2a价格)

  • 手机进入工程模式怎么退出(手机进入工程模式代码)

    手机进入工程模式怎么退出(手机进入工程模式代码)

  • 苹果11怎么用副卡发短信(苹果11怎么用副卡)

    苹果11怎么用副卡发短信(苹果11怎么用副卡)

  • 华为nova5pro怎么截屏(华为nova5pro怎么分屏)

    华为nova5pro怎么截屏(华为nova5pro怎么分屏)

  • 收银小票打印格式设置(收银小票打印文字)

    收银小票打印格式设置(收银小票打印文字)

  • 苹果有9和10吗(苹果有9嘛)

    苹果有9和10吗(苹果有9嘛)

  • 抖音手滑点赞取消别人会知道吗(抖音手滑点赞取消后改名字还能看到吗)

    抖音手滑点赞取消别人会知道吗(抖音手滑点赞取消后改名字还能看到吗)

  • 【PyG】与networkx的图转换(network python)

    【PyG】与networkx的图转换(network python)

  • Redis高频面试题汇总(上)(redis面试必会6题经典)

    Redis高频面试题汇总(上)(redis面试必会6题经典)

  • 普通人如何交五险一金
  • 固定资产盘盈为什么计入盈余公积
  • 增值税发票抵扣勾选平台
  • 发票右上角打印缺数字
  • 社会团体财政票据管理制度
  • 对公走账是什么意思
  • 小规模纳税人年应税销售额标准是
  • 外商独资企业资本金的使用
  • 视同销售收入计入会计利润吗
  • 房屋租赁费增值税专用发票几个点
  • 存在弃置费用的固定资产有哪些
  • 盈利能力分析对企业发展的意义
  • 住房补贴是现金还是转账
  • 增值税发票价格低于进项
  • 税收缴款书税务收现专用的用途
  • 软件企业两免三减半税收政策到期
  • 预估材料入账后冲回的步骤
  • 来料加工进料加工是免税的吗?
  • 实收金额比应收金额多
  • 现金支票丢了
  • 当年的成本发票必须当年结算吗
  • tp link无线路由器设置
  • 交易性金融资产的交易费用计入哪里
  • 员工离职补偿金计算方法
  • 鸿蒙工具箱使用视频
  • 小规模纳税人销售货物税率是多少
  • 应收账款需要计提坏账准备吗
  • 十个php高级应用题
  • 会计计量属性的是
  • 印花税怎么核算的
  • 无形资产的摊销计入什么科目
  • wordpress创建
  • PHP:imagealphablending()的用法_GD库图像处理函数
  • 什么情况下增长率是0
  • php日期差数
  • 张家界天门山介绍简介
  • php常用的魔术方法有哪些
  • 如何配置phpstudy
  • php怎么访问本地的网页
  • vue清空form数据再重新赋值
  • css如何应用
  • 使用什么指令可以清空memcached数据库中的所有数据
  • 季度报税有利润必须要报交所得税吗
  • 帝国cms如何使用
  • 如何隐藏应用软件华为
  • js变量作用范围
  • mysql将查询结果存到另一个表
  • 存货成本费用
  • 购买材料发票未到如何做账?
  • 采购流程内容
  • 个人去税务局开劳务发票要交多少税
  • 应收票据周转率怎么分析
  • 优惠券会计分录怎么做
  • 流动资金周转次数计算公式
  • 建筑工程劳务分包,工伤责任承担
  • 其他综合收益什么时候转留存收益什么时候转损益
  • 建筑业属于货物经营吗
  • 实缴发票和月结发票知乎
  • 应收账款多收了退回怎么做账
  • 公司账户美金入账后怎么做分录
  • 会计凭证装订的心得体会
  • sql server 判断数据是否存在
  • unix系统中目录采用什么结构
  • win10怎么获取
  • win7系统u盘打不开怎么办
  • 怎么在mac上看电视剧
  • windows取消隐藏文件夹
  • Windows RT 8.1 Update 3九月发布 届时将加入改进版锁屏
  • linux sort命令参数及用法详解
  • centos zsh
  • text date excel
  • opengl怎么导入模型
  • 使用jquery
  • dos查看内存命令
  • jqueryui dialog
  • 每天一篇文章锻炼口才的文章
  • 谷歌的全球化发展战略
  • 印花税核算有两种情况,是如何处理的?
  • 个人所得税必须企业代扣代缴吗
  • 2021年下半年财务部工作计划
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设