Reack Hooks 测试题

【1】Redux 中异步 Action 说法正确的是?

  • 异步 Action 是一种 Redux 支持的 特殊 Action
  • 异步 Action 必须 redux-thunk 中间件的支持
  • 异步 Action 是同步 Action 的一种组织形式
  • 异步 Action 不仅仅可以用于异步请求

CD

A: 异步 Action 其实是由多个同步 Action 的组合执行得到的一个概念,并不是一种特殊的机制

B: 异步 Action 需要中间件的支持,但不一定是 Redux-thunk

C: 正确, 异步 Action 只是同步 Action 的一种组织形式

D: 正确,异步 Action 可以用于任何异步场景,比如 setTimeout,不一定是服务器端请求

【2】如果希望一个 React 组件不渲染任何内容,可以如何去做?

  • 返回 undefined

  • 返回 null

  • 返回空字符

  • 组件返回 false

BCD

在处理 falsy 的值时,React 遇到 null, 空字符串或者 false 不会渲染任何内容。undefined会导致出错,0 则直接渲染为 0

【3】能够实现全局状态管理的机制或者框架包括哪些?

  • useRef
  • React Context
  • Redux
  • lodash

BC

A: useRef 是在一个组件的多次渲染之间共享数据,而不是全局状态

B: Context 就是设计为做全局状态的,事实上其它的框架比如 Redux 也是基于 Context 的

C:Redux 是 Facebook 提供的官方全局状态管理机制,也是最为主流的状态框架

D: lodash 是工具库,和 React 状态管理没有必然关系

【4】关于 useCallback 的说法错误的是?

  • useCallback 可以用 useMemo 实现
  • useCallback 可以避免重复创建函数
  • useCallback 必须提供依赖项定义
  • useCallback 不能在条件语句中执行

B

A: useCallback 可以用 useMemo 来实现,相当于返回值是一个回调函数。

B:useCallback 其实并没有避免重复创建函数,因为在 useCallback(() => {}, [deps]) 的形式中,每次运行都会创建一个函数。useCallback 只是可以决定是不是要使用新的函数。在 依赖项不变的时候,就始终返回之前的,从而避免组件的重复渲染。

C: 如果不给 useCallback 提供依赖项定义,那么和不使用 useCallback 是一样的,所以必须提供

D:任何 Hook 都不能在条件语句中执行

【5】关于 useCallback, useMemo, useEffect 的依赖项定义说法错误的是?

  • 依赖项发生变化则 Hook 会重新执行

  • 所有在 Hook 中使用的状态都必须在依赖项中指定

  • 依赖项需要通过数组定义

  • 依赖项可以是一个变量

B

在默认的项目模板中,其实依赖项如果没有指定,那么只是显示一个 warning ,而不是 error。因为如果你非常确定不需要监听某个依赖项的变化,是可以不去指定的。虽然默认来说,依赖项是通过静态数组去提供的,但是如果你确定依赖项的内容,那么通过变量数组也是可以的。

【6】useEffect 的作用有哪些?

  • 发起异步请求

  • 聚合业务逻辑

  • 捕获组件异常

  • 提高渲染性能

AB

useEffect 主要是产生副作用,以及通过返回的回调函数进行副作用的清理。因此答案是 A 和 B。和异常捕获以及渲染性能无关。

【7】React 中为什么要使用不可变数据(immutable)?

  • 提升渲染性能

  • 方便数据处理

  • 易于理解和维护

  • 方便检测数据变化

AD

A:不可变数据可以很容易地让一个组件知道自己的属性是否发生了变化,从而决定是否要重新渲染,因此可以提升渲染性能。

B:不可变数据其实是比普通的数据更难处理的,因为每次修改都要创建新的对象。

C:读取不可变数据和读取普通数据,代码是完全一样的,所以并没有变得更容易理解和维护。

D:是的,不可变数据只需要通过引用比较,就能知道是否发生了变化。

【8】在使用 create-react-app 创建的 React 应用中,JSX 是由谁去解析的?

  • Webpack

  • React

  • Babel

  • ESLint

C

在默认的项目模板中,JSX 是由 Babel 进行处理的,将其转换为 React.createElement 的形式,所以 JSX 是非常易于学习和理解的。

【9】哪个声明周期方法无法通过函数组件实现?

  • componentDidMount
  • componentDidUpdate
  • componentDidCatch
  • componentShoudUpdate

C

就目前来说,还有一些 Class 组件的声明周期方法没有对应的 Hooks,比如 componentDidCatch,所以并没有完全替代。但是大部分场景下都是可以替代的,我们也应该尽量使用函数组件去实现业务功能。

【10】React Hooks 带来的好处包括哪些?

  • 编译速度更快

  • 方便逻辑重用

  • 实现关注分离

  • 易于单元测试

BC

A: 编译速度主要取决于使用的语言和编译工具,与是否是 Hooks 无关。

B: 方便逻辑重用正是 Hooks 的主要目的。Hooks 能够直接使用组件的状态并触发组件刷新,从而可以提取业务逻辑进行重用。

C: 关注分离是 Hooks 带来的另外一个好处,它能够让你将相关的代码写在一起,而不是分散在生命周期的不同方法中。

D: Hooks 的单元测试基本上等价于组件的单元测试,并没有变得更容易。

【11】Server Components 能带来的好处有哪些?

  • 减少打包体积
  • 提升渲染性能
  • 代码更容易维护
  • 降低应用复杂度

BC

Server Components 允许通过服务器端去执行某个组件的逻辑并生成结果,因此,它能带来的好处包括两方面,一个是让下载到浏览器端的包体积变小,另一个是服务器端的渲染。因为可以直接访问数据库等数据源,在需要多个请求时性能更高

【12】关于单元测试说法错误的是?

  • Hooks 就是普通函数,所以通过函数调用来进行单元测试
  • 每一个自定义 Hooks 都需要对其单独进行单元测试
  • Class 组件和函数组件的单元测试机制是类似的
  • Redux 可以单独进行单元测试

AB

A: Hooks 需要函数组件的上下文,因此需要通过组件来测试

B:如果自定义 Hooks 只是为了拆分组件的复杂度,而不是为了逻辑的复用,那么应该通过使用它的组件进行单元测试,而无需自己单独测试。

C: 对于组件的单元测试,都是通过渲染 DOM 节点,并检测 DOM 节点的结构来完成的,对于函数组件和 Class 组件是一样的

D: Redux 是纯粹的数据状态管理框架,可以脱离于 React 独立运行,因此也可以单独进行单元测试

【13】按需加载的机制中,import() 语句是由谁处理的?

  • React.lazy
  • Babel
  • Webpack
  • 浏览器

C

import 语句作为一个 JS 语言的语法提案,并没有正式纳入标准,但是 Webpack 利用了这个语法实现了代码的分包。

【14】实现嵌套路由的关键点有哪些?

  • URL 参数识别
  • URL 的模式匹配
  • 支持动态路由
  • 使用 children 属性渲染子组件

BD

要实现嵌套路由,关键在于理解 React 中路由实现的原理。嵌套路由意味着一个 URL 能够同时匹配到嵌套的组件,因此需要支持模式匹配。同时,为了让父组件能够根据路由去局部渲染子组件,因此需要使用到 children 属性

【15】直接将对话框在父组件中声明有哪些缺点?

  • 语义不准确
  • 难以重构
  • 对话框的控制比较繁琐
  • 降低了性能

ABC

对话框这种 UI 模式其实和独立窗口打开的一个页面是非常类似的,它们本质上都是让用户聚焦到某一个独立的业务功能上进行操作,因此对话框的创建和管理其实也应该尽量独立,而不是绑定在某个父组件中。因此答案是 ABC

【16】Hooks 可以给表单处理带来的好处有哪些?

  • 方便了状态管理
  • 方便了表单布局
  • 方便了表单验证
  • 方便创建动态表单

A

Hooks 主要是为表单处理提供了更方便的状态管理机制。和布局、验证以及动态性无关

【17】软件复杂度的根源来自于什么?

  • 低效的算法实现
  • 代码之间的互相依赖
  • 庞大的组件数量
  • 复杂的业务功能

B

复杂的依赖关系是软件复杂度的根源。如果每一个模块都完全独立,彼此之间没有任何依赖,那么其实开发多模块的软件和开发单个模块同样地简单

【18】React 中如何保证状态的一致性?

  • 使用全局状态
  • 状态最小化原则
  • 避免中间状态
  • 使用自定义 Hooks

BC

维持状态一致性才能让代码逻辑更加简单、易于维护。包括状态最小化,和避免中间状态确保唯一数据源两个原则

【19】自定义 Hooks 的使用场景包括哪些?

  • 拆分复杂组件
  • 封装通用逻辑
  • 监听浏览器状态
  • 缓存计算结果

ABC

A: 正确。在 React 函数组件中使用自定义 Hooks,应该就像使用普通函数一样,尽量去做逻辑的隔离

B: 正确。逻辑重用正是 Hooks 要解决的核心问题

C: 正确。Hooks 让你更方便地进行浏览器状态的监听

D: 错误。缓存计算结果通常是内置 Hook useMemo 提供的,或者一些第三方的 library 可以提供,比如 lodash, reselect 等等,和自定义 Hooks 无关

【20】Hooks, HOC 和 render props 说法错误的是

  • 三者都可以实现逻辑的复用
  • Hooks 能够完全替代 HOC 和 render props
  • HOC 主要实现数据逻辑的复用
  • render props 可以提供 UI 展现的复用

B

A:正确,三者都是为了逻辑复用

B:不一定,对于一些 Controller 类型的 HOC,或者需要复用 UI 渲染的 render props ,都不太适合用 Hooks 去实现。

C: HOC 中一般作为 Controller 或者绑定外部数据源等数据逻辑

D:正确,render props 可以在容器组件中去渲染 UI