React 面试问题(中高级)
以下是一些 React 面试中可能会问到的常见高级问题。如果你即将参加面试,祝你好运,希望这些内容能对你有所帮助。
什么是 React Hooks?
React Hooks 是 React 16.8 版本中的新增功能。它允许你使用状态和其他 React 功能,而无需将函数式组件转换为类。
Hooks 用更少的代码完成同样的工作,而更少的代码意味着产生错误的机会更少。
基本钩子
useState
- 返回一个有状态的值和一个更新它的函数。
useEffect
- 让我们在函数组件中执行副作用
useContext
- 提供一个简单的函数,通过任何子组件中的 Context Provider 的值 prop 来访问数据
附加钩子
useReducer
- 状态管理,例如 redux,用于在较小的应用程序中管理状态,而不必使用第三方状态管理库
使用回调
- 记忆回调函数,因此它们不会在每次重新渲染时重新创建。
使用备忘录
- 存储昂贵操作的结果
useRef
- 让我们在函数组件中执行副作用
useImperativeHandle
- 与 forwardRef 一起使用,允许您修改从父组件公开的 ref 实例
useLayoutEffect
- 在 React 执行完所有 DOM 变更后,立即同步运行
useDebugValue
- 允许您在自定义 Hooks 旁边显示其他有用的信息,并带有可选格式。
什么是上下文?
Context 提供了一种通过组件树传递数据的方法,而无需在每个级别手动传递 props。
它旨在共享可被视为 React 组件树的全局数据。
注意:请谨慎使用,因为它会使组件复用更加困难。考虑使用组件组合,因为它通常比上下文更简单。
组件之间如何传递数据?
- 要将数据从父级传递到子级,请使用 props
- 要将数据从子级传递到父级,请使用回调
- 在兄弟姐妹之间以及其他任何地方传递数据
- 也可以使用 React 的 Context API
- 对于中大型有状态应用程序,请使用状态管理库。例如: Redux、MobX 和 Recoil
React 有哪些局限性?
首先,JSX 会使编码变得复杂。对于初学者来说,它的学习曲线会比较陡峭。
其次,React 文档不够用户友好且不够全面。
第三,每个 React 项目对于工程师来说都是独一无二的,因为他们将依赖多种技术来融入他们的项目中。
什么是支柱钻孔以及如何避免它?
Prop Drilling是将数据从一个组件传递到深层嵌套组件的过程。这会成为一个问题,因为其他组件会包含它们不需要的数据。
此外,这会使组件难以维护。
避免 prop 钻取的常见方法是使用 React 上下文和状态管理库。
支柱钻井的一些缺点
- 原本不应该了解数据的组件变得不必要地复杂
- 更难维护。
dangerlySetInnerHTML 有什么用?
此属性是 React 在浏览器中使用 innerHTML 的替代方案。它将在组件中渲染原始 HTML。
应该限制它的使用,因为它可能会使用户面临潜在的跨站点脚本攻击。
列举一些优化 React 应用程序性能的技术。
首先,使用 React.Suspense 和 React.Lazy 实现组件的延迟加载。这样只会在需要时加载组件。
import LazyComponent from './LazyComponent';
const LazyComponent = React.lazy(() => import('./LazyComponent'));
第二,使用 React.memo 进行组件记忆化。React.memo
是一个高阶组件,它会渲染组件并记忆结果。在下次渲染之前,如果新的 props 相同,React 会重用已记忆的结果,跳过下次渲染。
import React from 'react';
const MyComponent = React.memo(props => {
/* render only if the props changed */
});
注意:如果 React.memo 在其实现中具有 useState, useReducer 或 useContext Hook,则当状态或上下文发生变化时它仍会重新渲染。
组件使用相同 props 渲染的次数越多,
输出就越重,计算成本就越高,组件就越有可能需要被包装在 React.memo() 中。
第三,使用 React.Fragment 避免向 DOM 添加额外的节点 React Fragment 不会在 DOM 中产生任何额外的元素,Fragment 的子组件将在没有任何包装 DOM 节点的情况下进行渲染。
这是一种比在代码中添加 div 更简洁的替代方法。
function App() {
return (
<React.Fragment>
<h1>Best App</h1>
<p>Easy as pie!</p>
</React.Fragment>
);
}
您还可以使用简短语法 <></> 来声明片段。
function App() {
return (
<>
<h1>Best App</h1>
<p>Easy as pie!</p>
</>
);
}
第四,在 Redux 中使用Reselect / Re-reselect
避免频繁重新渲染。Reselect是一个用于构建 memoized selectors 的库,常用于 Redux。
优势
- 选择器可以计算派生数据,从而允许 Redux 存储尽可能小的状态。
- 选择器非常高效。除非参数发生变化,否则选择器不会重新计算。
- 选择器是可组合的。它们可以用作其他选择器的输入。
Re-reselect 是 Reselect 的轻量级包装器,可通过更深层次的记忆和缓存管理来增强选择器。
有用:
- 当使用一个或几个不同的参数顺序调用时,保留选择器的缓存
- 将相似的选择器合并为一个
- 在多个组件实例之间共享带有 props 的选择器
- 在运行时实例化选择器
- 使用自定义缓存策略增强重新选择
最后,使用生产版本
确保应用程序在部署之前已捆绑以供生产。
什么是和解?
当组件的 props 或 state 发生变化时,React 会通过比较新返回的元素与之前渲染的元素来决定是否需要实际更新 DOM。如果它们不相等,React 将更新 DOM。这个过程称为协调 (reconciliation)。
什么是高阶组件?
高阶组件(HOC)是 React 中用于复用组件逻辑的高级技术。它是一个接受一个组件作为参数并返回一个新组件的函数。
const EnhancedComponent = higherOrderComponent(WrappedComponent);
HOC 在第三方 React 库中很常见,例如 Redux 的 connect 和 Relay 的 createFragmentContainer。
HOC 可用于多种用例:
- 有条件地渲染组件。
- 为组件提供特定的样式。
- 为其他组件提供任何道具。
- 当组件等待数据时显示加载器
children 道具是什么?
它是一个 prop,允许我们将组件作为数据传递给其他组件,就像任何其他 prop 一样。组件的开始标签和结束标签之间的组件树将作为 children prop 传递给该组件。
const MyComponent = ({title, children}) => {
return (
<>
<h1>{title}</h1>
{children}
</>
);
}
import { MyComponent } from './MyComponent';
const App = () => {
return (
<MyComponent title=“Simple React App”>
<h2>Very Kewl Feature</h2>
</MyComponent>
);
}
如何将参数传递给事件处理程序或回调?
您可以使用箭头函数来包装事件处理程序并传递参数:
<button onClick={() => this.handleClick(id)} />
您还可以将参数传递给定义为箭头函数的函数
const handleClick = (id) => () => {
console.log(`The id is ${id}`)
};
<button onClick={this.handleClick(id)} />
为什么我们需要向 setState() 传递一个函数?
setState() 是一个异步操作。出于性能方面的考虑,React 会批量更改状态。这意味着状态可能不会在 setState() 调用后立即改变。
调用 setState() 时我们不应该依赖当前状态,因为我们无法确定该状态是什么。
// Wrong
this.setState({
counter: this.state.counter + 1
})
解决方案是将一个函数传递给 setState(),并将之前的状态作为参数。
// Correct
this.setState((prevState) => ({
counter: prevState.counter + 1
}))
即使你暂时不需要,也可以随时收藏🔖。以后你寻找新职位的时候,可能需要刷新/回顾一下。
如果你想支持我 -请给我买杯咖啡
如果您不想阅读,请观看视频🎥格式: