文章目录
-
-
- React篇
-
- 1. React 的核心理念是什么?
- 2. React 的虚拟 DOM 是什么?如何提升性能?
- 3. React 的 `useState` 和类组件的 `setState` 有什么区别?
- 4. React 的 `useEffect` 如何替代生命周期方法?
- 5. React 的 `useReducer` 有什么优势?
- 6. React 的 `memo` 如何优化性能?
- 7. React 的 `useCallback` 和 `useMemo` 有什么区别?
- 8. React 的 Context 如何实现状态共享?
- 9. React 的 `forwardRef` 有什么作用?
- 10. React 的 `useImperativeHandle` 如何自定义暴露接口?
- 11. React 的渲染流程是怎样的?
- 12. React 的 `key` 属性有什么作用?
- 13. React 的 `setState` 是同步还是异步?
- 14. React 的 `useEffect` 如何避免无限循环?
- 15. React 的 Hooks 和类组件相比有什么优势?
- 16. React 的 `useRef` 有哪些用途?
- 17. React 的 `lazy` 和 `Suspense` 如何实现懒加载?
- 18. React 的 `useContext` 如何优化性能?
- 19. React 的 `useEffect` 如何处理异步操作?
- 20. React 的 `Fragment` 有什么作用?
- 21. React 的 `useLayoutEffect` 和 `useEffect` 有什么区别?
- 22. React 的 `useTransition` 如何优化交互?
- 23. React 的 `useDeferredValue` 有什么作用?
- 24. React 的 `StrictMode` 有什么作用?
- 25. React 的 `createPortal` 如何实现弹窗?
- 26. React 的组件设计原则有哪些?
- 27. React 的 `useCallback` 如何优化子组件渲染?
- 28. React 的 `useMemo` 如何优化昂贵计算?
- 29. React 的自定义 Hook 如何设计?
- 30. React 的 `useReducer` 如何与 Context 结合?
- 31. React 的 `useEffect` 如何处理事件监听?
- 32. React 的 `memo` 如何自定义比较逻辑?
- 33. React 的 `useRef` 如何保存上一次状态?
- 34. React 的 `useLayoutEffect` 如何避免闪烁?
- 35. React 的 `useTransition` 如何优化大数据渲染?
- 36. React 的 `useDeferredValue` 如何与输入框结合?
- 37. React 的 Context 如何避免不必要重渲染?
- 38. React 的 `forwardRef` 如何与 Hooks 结合?
- 39. React 的 `useEffect` 如何模拟类组件生命周期?
- 40. React 的 `useCallback` 如何与 `memo` 协同?
- 41. React 的 `useReducer` 如何处理复杂表单?
- 42. React 的 `useMemo` 如何优化列表渲染?
- 43. React 的 `useContext` 如何与 Redux 对比?
- 44. React 的 `useEffect` 如何处理竞态条件?
- 45. React 的 `lazy` 如何与路由结合?
- 46. React 的 `useRef` 如何实现防抖?
- 47. React 的 `useMemo` 如何与自定义 Hook 结合?
- 48. React 的 `useEffect` 如何与外部状态同步?
- 49. React 的 `useContext` 如何实现动态主题切换?
- 50. React 的 `useReducer` 如何实现异步操作?
- 51. React Router 的核心原理是什么?
- 52. React Router 的 `BrowserRouter` 和 `HashRouter` 有什么区别?
- 53. React Router 的动态路由如何实现?
- 54. React Router 的 `useNavigate` 如何实现编程式导航?
- 55. React Router 的 `Outlet` 有什么作用?
- 56. React Router 的路由守卫如何实现?
- 57. React Router 的懒加载如何实现?
- 58. Redux 的核心概念有哪些?
- 59. Redux 的 `connect` 如何连接组件?
- 60. Redux 的 `useSelector` 和 `useDispatch` 有什么作用?
- 61. Redux 的中间件是如何工作的?
- 62. Redux Thunk 如何实现异步操作?
- 63. Redux Saga 如何处理异步操作?
- 64. Redux Toolkit 有什么优势?
- 65. Redux Toolkit 的 `createAsyncThunk` 如何使用?
- 66. React Router 的 `useLocation` 有什么作用?
- 67. React Router 的 `NavLink` 如何实现高亮?
- 68. Redux 的 `combineReducers` 如何组织 reducer?
- 69. Redux 的状态如何实现持久化?
- 70. React Router 的 `useSearchParams` 如何处理查询参数?
- 71. Redux 的 `reselect` 有什么作用?
- 72. React Router 的 `useRoutes` 如何替代 `Routes`?
- 73. Redux 的状态如何与 React Router 集成?
- 74. Redux Toolkit 的 `createEntityAdapter` 有什么作用?
- 75. React Router 的 `useMatch` 如何判断路由匹配?
- 76. React Router 的路由参数如何传递和获取?
- 77. React Router 的 `useRoutes` 如何实现动态路由?
- 78. React Router 如何实现路由动画?
- 79. React Router 的 `useNavigate` 如何处理回退?
- 80. React Router 的 `useLocation` 如何监听路径变化?
- 81. Redux Toolkit 的 `createSlice` 如何简化开发?
- 82. Redux 如何实现状态快照和回滚?
- 83. Redux Toolkit 的 `createAsyncThunk` 如何处理错误?
- 84. Redux 的 `reselect` 如何优化性能?
- 85. React Router 的 `useMatch` 如何与条件渲染结合?
- 86. Redux Toolkit 的 `configureStore` 如何优化配置?
- 87. React Router 的 `useSearchParams` 如何实现分页?
- 88. Redux 的状态如何与本地存储同步?
- 89. React Router 的 `Outlet` 如何传递上下文?
- 90. Redux Toolkit 的 `createEntityAdapter` 如何优化列表?
- 91. React Router 的 `useNavigate` 如何传递状态?
- 92. Redux 的 `combineReducers` 如何处理嵌套状态?
- 93. React Router 的 `useRoutes` 如何实现条件路由?
- 94. Redux Toolkit 的 `createSelector` 如何与 `useSelector` 结合?
- 95. React Router 的 `useLocation` 如何与 Redux 集成?
- 96. Redux 的中间件如何实现日志功能?
- 97. React Router 的 `NavLink` 如何自定义样式?
- 98. Redux Toolkit 的 `createSlice` 如何处理异步逻辑?
- 99. React Router 的 `useNavigate` 如何实现条件跳转?
- 100. Redux 的状态如何与 React Router 协同优化?
- 101. React 的性能优化有哪些常见方法?
- 102. React 的 `memo` 如何避免子组件重渲染?
- 103. React 的 `useMemo` 如何优化复杂计算?
- 104. React 的 `useCallback` 如何优化事件处理?
- 105. React 的 `key` 如何提升列表渲染性能?
- 106. React 的懒加载如何提升首屏性能?
- 107. React 的批量更新如何优化状态更新?
- 108. React 18 的并发渲染是什么?
- 109. React 18 的 `useTransition` 如何优化用户体验?
- 110. React 18 的 `useDeferredValue` 如何优化渲染?
- 111. React 的 `useEffect` 如何优化依赖项?
- 112. React 的 `Suspense` 如何与并发渲染结合?
- 113. React 的 `useLayoutEffect` 如何优化布局计算?
- 114. React 的 `shouldComponentUpdate` 如何优化类组件?
- 115. React 的 `useReducer` 如何优化复杂状态?
- 116. React 18 的自动批处理如何提升性能?
- 117. React 的 `useRef` 如何优化不受控组件?
- 118. React 的 `useMemo` 如何优化 Context 消费者?
- 119. React 的 `SuspenseList` 如何协调多个 Suspense?
- 120. React 的 `useEffect` 如何优化数据获取?
- 121. React 18 的 `startTransition` 如何手动控制?
- 122. React 的 `useImperativeHandle` 如何优化 ref 暴露?
- 123. React 的 `useMemo` 如何优化大数据渲染?
- 124. React 18 的并发特性如何提升交互性?
- 125. React 的 `useRef` 如何优化动画?
- 126. React 的 `useMemo` 如何与 `useCallback` 协同优化?
- 127. React 的 `useEffect` 如何优化条件执行?
- 128. React 的 `useRef` 如何优化频繁更新?
- 129. React 18 的 `useTransition` 如何优化列表过滤?
- 130. React 的 `useDeferredValue` 如何优化子组件?
- 131. React 的 `Suspense` 如何优化数据获取?
- 132. React 的 `useLayoutEffect` 如何优化同步更新?
- 133. React 的 `useMemo` 如何优化虚拟列表?
- 134. React 18 的并发渲染如何优化大数据?
- 135. React 的 `useRef` 如何优化防抖输入?
- 136. React 的 `useEffect` 如何优化异步清理?
- 137. React 的 `memo` 如何优化嵌套组件?
- 138. React 18 的 `useTransition` 如何优化表单提交?
- 139. React 的 `useMemo` 如何优化条件渲染?
- 140. React 的 `useRef` 如何优化滚动位置?
- 141. React 18 的 `useDeferredValue` 如何优化搜索建议?
- 142. React 的 `useEffect` 如何优化事件节流?
- 143. React 的 `memo` 如何优化动态列表?
- 144. React 18 的并发渲染如何优化 SSR?
- 145. React 的 `useMemo` 如何优化高阶组件?
- 146. React 的 `useRef` 如何优化第三方库集成?
- 147. React 18 的 `useTransition` 如何优化导航?
- 148. React 的 `useMemo` 如何优化 CSS-in-JS?
- 149. React 的 `useEffect` 如何优化 WebSocket?
- 150. React 18 的并发渲染如何优化表单验证?
- 151. React 的 Fiber 架构是什么?
- 152. React 的 diff 算法如何工作?
- 153. React 的渲染流程有哪些阶段?
- 154. React 的 `setState` 是如何实现的?
- 155. React 的 Hooks 是如何实现的?
- 156. React 的 `useEffect` 是如何实现的?
- 157. React 的虚拟 DOM 如何提升性能?
- 158. React 的调度器(Scheduler)是如何工作的?
- 159. React 的 `useMemo` 是如何实现的?
- 160. React 的 `useCallback` 是如何实现的?
- 161. React 的 `Suspense` 是如何实现的?
- 162. React 的 `useTransition` 是如何实现的?
- 163. React 的 `useDeferredValue` 是如何实现的?
- 164. React 的 Context 是如何实现的?
- 165. React 的 `forwardRef` 是如何实现的?
- 166. React 的事件系统是如何实现的?
- 167. React 的 `useReducer` 是如何实现的?
- 168. React 的 `memo` 是如何实现的?
- 169. React 的 `useRef` 是如何实现的?
- 170. React 的 `lazy` 是如何实现的?
- 171. React 的复杂表单如何优化性能?
- 172. React 的树形组件如何优化渲染?
- 173. React 的拖拽组件如何实现?
- 174. React 的 SSR 如何与 Hydration 结合?
- 175. React 的错误边界是如何实现的?
- 176. React 的高阶组件(HOC)如何实现动态代理?
- 177. React 的 Render Props 如何处理复杂逻辑?
- 178. React 的自定义 Hook 如何实现状态共享?
- 179. React 的动态表格如何优化大数据渲染?
- 180. React 的复杂动画如何实现?
- 181. React 的微前端如何实现?
- 182. React 的复杂状态机如何实现?
- 183. React 的动态表单如何实现字段扩展?
- 184. React 的复杂列表如何实现拖拽排序?
- 185. React 的复杂路由如何实现权限控制?
- 186. React 的复杂组件如何实现懒加载?
- 187. React 的复杂状态如何与 Redux Toolkit 结合?
- 188. React 的复杂布局如何实现响应式?
- 189. React 的复杂搜索如何实现高性能?
- 190. React 的复杂图表如何集成第三方库?
- 191. React 的复杂权限如何实现动态菜单?
- 192. React 的复杂模态框如何实现?
- 193. React 的复杂时间线如何实现?
- 194. React 的复杂文件上传如何实现?
- 195. React 的复杂分页如何实现动态加载?
- 196. React 的复杂树形选择器如何实现?
- 197. React 的复杂时间选择器如何实现?
- 198. React 的复杂拖拽上传如何实现?
- 199. React 的复杂步骤条如何实现?
- 200. React 的复杂实时聊天如何实现?
-
React篇
1. React 的核心理念是什么?
答案解析
React 的核心理念是声明式编程和组件化开发。
- 声明式:开发者只需描述 UI 的状态,React 负责将其高效渲染到 DOM。
- 组件化:将 UI 拆分为独立、可复用的组件,提升代码可维护性。
- 虚拟 DOM:通过内存中的轻量表示优化更新效率。
代码示例:
function Button({ text }) {
return <button>{text}</button>;
}
解析:
- 高效性:虚拟 DOM 和 diff 算法减少直接操作真实 DOM 的开销。
- 对比命令式:如 jQuery 需手动操作 DOM,React 更简洁。
应用场景:构建复杂、可复用的 UI 组件。
2. React 的虚拟 DOM 是什么?如何提升性能?
答案解析
虚拟 DOM 是真实 DOM 的内存表示,React 通过它优化更新。
- 工作原理:状态变化时生成新虚拟 DOM,与旧版本对比(diff),仅更新差异部分。
- 性能提升:批量更新、减少直接 DOM 操作。
代码示例:
function App() {
const [count, setCount] = React.useState(0);
return <div>{count}<button onClick={() => setCount(count + 1)}>Add</button></div>;
}
解析:
- diff 算法:同层比较,复用节点。
- 优化:
key
属性加速列表 diff。
应用场景:动态列表、大型表单。
3. React 的 useState
和类组件的 setState
有什么区别?
答案解析
- useState:函数组件的 Hook,返回状态和更新函数,更新是替换式。
- setState:类组件方法,合并状态,支持回调。
代码示例:
// useState
function Counter() {
const [count, setCount] = React.useState(0);
setCount(count + 1); // 替换
}
// setState
class Counter extends React.Component {
state = { count: 0 };
handleClick = () => {
this.setState({ count: this.state.count + 1 }, () => console.log("Updated"));
};
}
解析:
- 合并:
setState
合并对象,useState
需手动合并。 - 回调:
setState
支持更新后回调,useState
用useEffect
。
应用场景:useState
适合函数组件,setState
用于旧代码迁移。
4. React 的 useEffect
如何替代生命周期方法?
答案解析
useEffect
统一处理副作用,替代类组件的生命周期。
- 挂载:空依赖数组模拟
componentDidMount
。 - 更新:依赖变化模拟
componentDidUpdate
。 - 卸载:返回清理函数模拟
componentWillUnmount
。
代码示例:
function Example() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
fetchData().then(setData); // 挂载
return () => console.log("Cleanup"); // 卸载
}, []); // 空依赖
React.useEffect(() => {
console.log("Data updated:", data); // 更新
}, [data]);
return <div>{data}</div>;
}
解析:
- 灵活性:按依赖粒度控制执行。
- 注意:避免无限循环,谨慎选择依赖。
应用场景:数据获取、事件监听。
5. React 的 useReducer
有什么优势?
答案解析
useReducer
管理复杂状态逻辑,替代 useState
。
- 优势:集中式状态更新,类似 Redux 的 reducer 模式。
代码示例:
const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case "increment": return { count: state.count + 1 };
default: return state;
}
}
function Counter() {
const [state, dispatch] = React.useReducer(reducer, initialState);
return <button onClick={() => dispatch({ type: "increment" })}>{state.count}</button>;
}
解析:
- 对比
useState
:更适合多状态联动。 - 可预测性:状态变化逻辑清晰。
应用场景:表单管理、复杂计数器。
6. React 的 memo
如何优化性能?
答案解析
React.memo
是高阶组件,缓存组件渲染,防止不必要更新。
- 原理:浅比较 props,props 不变则跳过渲染。
代码示例:
const Child = React.memo(({ value }) => {
console.log("Child rendered");
return <div>{value}</div>;
});
function Parent() {
const [count, setCount] = React.useState(0);
return (
<>
<Child value="static" />
<button onClick={() => setCount(count + 1)}>{count}</button>
</>
);
}
解析:
- 优化:避免父组件更新导致子组件重渲染。
- 限制:仅浅比较,深层对象需自定义比较。
应用场景:静态子组件、列表项。
7. React 的 useCallback
和 useMemo
有什么区别?
答案解析:
- useCallback:缓存函数,防止重复创建。
- useMemo:缓存值,优化计算结果。
代码示例:
function Example() {
const [count, setCount] = React.useState(0);
const increment = React.useCallback(() => setCount(count + 1), [count]);
const doubled = React.useMemo(() => count * 2, [count]);
return <button onClick={increment}>{doubled}</button>;
}
解析:
- useCallback:返回函数引用。
- useMemo:返回计算值。
- 性能:减少子组件重复渲染或昂贵计算。
应用场景:事件处理、计算属性。
8. React 的 Context 如何实现状态共享?
答案解析
Context 提供跨组件层级的数据传递,避免 props 逐层透传。
- 步骤:创建 Context、Provider 提供值、Consumer 或
useContext
消费。
代码示例:
const ThemeContext = React.createContext("light");
function App() {
return (
<ThemeContext.Provider value="dark">
<Child />
</ThemeContext.Provider>
);
}
function Child() {
const theme = React.useContext(ThemeContext);
return <div>Theme: {theme}</div>;
}
解析:
- 性能:Provider 更新时所有消费者重渲染。
- 优化:结合
useMemo
减少重复。
应用场景:主题切换、用户信息。
9. React 的 forwardRef
有什么作用?
答案解析
forwardRef
将 ref 转发到子组件,允许父组件访问子组件的 DOM 或实例。
- 作用:解决函数组件无法直接绑定 ref 的问题。
代码示例:
const Input = React.forwardRef((props, ref) => (
<input ref={ref} {...props} />
));
function Parent() {
const inputRef = React.useRef();
const focus = () => inputRef.current.focus();
return (
<>
<Input ref={inputRef} />
<button onClick={focus}>Focus</button>
</>
);
}
解析:
- 原理:ref 作为第二个参数传递。
- 搭配:常与
useImperativeHandle
使用。
应用场景:表单聚焦、动画控制。
10. React 的 useImperativeHandle
如何自定义暴露接口?
答案解析
useImperativeHandle
配合 forwardRef
,自定义暴露给父组件的 ref 接口。
- 作用:限制暴露内容,增强封装性。
代码示例:
const Input = React.forwardRef((props, ref) => {
const inputRef = React.useRef();
React.useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
}));
return <input ref={inputRef} />;
});
function Parent() {
const ref = React.useRef();
return (
<>
<Input ref={ref} />
<button onClick={() => ref.current.focus()}>Focus</button>
</>
);
}
解析:
- 控制:仅暴露
focus
,隐藏 DOM。 - 安全性:防止直接操作内部。
应用场景:封装组件接口。
11. React 的渲染流程是怎样的?
答案解析
React 的渲染流程分为三个阶段:
- 触发更新:状态或 props 变化。
- 调和(Reconciliation):生成新虚拟 DOM,diff 对比。
- 提交(Commit):更新真实 DOM。
代码示例:
function App() {
const [count, setCount] = React.useState(0);
return <button onClick={() => setCount(count + 1)}>{count}</button>;
}
解析:
- Fiber:React 16+ 使用 Fiber 架构,支持中断和优先级。
- 批量更新:事件中多次 setState 合并。
应用场景:理解性能瓶颈。
12. React 的 key
属性有什么作用?
答案解析
key
是 React diff 算法的标识,帮助高效更新列表。
- 作用:标记元素身份,减少重复渲染。
代码示例:
function List() {
const items = ["A", "B", "C"];
return (
<ul>
{items.map(item => <li key={item}>{item}</li>)}
</ul>
);
}
解析:
- 错误用法:用索引作为
key
,可能导致状态混乱。 - 优化:使用唯一 ID。
- 效果:提升列表增删性能。
应用场景:动态列表、表格。
13. React 的 setState
是同步还是异步?
答案解析
setState
在 React 事件中是异步的,在原生事件或 setTimeout 中是同步的。
- 原因:React 批量更新优化性能。
代码示例:
class App extends React.Component {
state = { count: 0 };
handleClick = () => {
this.setState({ count: this.state.count + 1 });
console.log(this.state.count); // 旧值
setTimeout(() => this.setState({ count: this.state.count + 1 }), 0);
};
render() {
return <button onClick={this.handleClick}>{this.state.count}</button>;
}
}
解析:
- 异步:React 控制的事件。
- 同步:非 React 控制上下文。
- 解决:使用回调或
useEffect
。
应用场景:状态更新调试。
14. React 的 useEffect
如何避免无限循环?
答案解析
useEffect
无限循环通常因依赖项变化触发,需正确管理依赖数组。
- 方法:确保依赖稳定,避免直接修改。
代码示例:
function Example() {
const [count, setCount] = React.useState(0);
React.useEffect(() => {
setCount(count + 1); // 错误:无限循环
}, [count]);
// 正确
React.useEffect(() => {
console.log("Mounted");
}, []);
}
解析:
- 问题:依赖项频繁变化。
- 解决:空数组或稳定引用(如
useCallback
)。 - 工具:ESLint
react-hooks/exhaustive-deps
。
应用场景:副作用管理。
15. React 的 Hooks 和类组件相比有什么优势?
答案解析
Hooks 提供函数式编程范式,优于类组件:
- 复用性:逻辑可抽取为自定义 Hook。
- 简洁性:无
this
绑定,代码更清晰。 - 状态管理:更细粒度控制。
代码示例:
function useCounter() {
const [count, setCount] = React.useState(0);
return { count, increment: () => setCount(count + 1) };
}
function App() {
const { count, increment } = useCounter();
return <button onClick={increment}>{count}</button>;
}
解析:
- 类组件:生命周期分散,复用困难。
- Hooks:集中逻辑,易测试。
应用场景:现代 React 开发。
16. React 的 useRef
有哪些用途?
答案解析
useRef
创建持久化引用,主要用途:
- 访问 DOM:绑定到元素获取实例。
- 保存变量:跨渲染保持值不变。
代码示例:
function Input() {
const inputRef = React.useRef(null);
const countRef = React.useRef(0);
const focus = () => inputRef.current.focus();
const increment = () => countRef.current++;
return (
<>
<input ref={inputRef} />
<button onClick={focus}>Focus</button>
<button onClick={increment}>Count: {countRef.current}</button>
</>
);
}
解析:
- 不变性:不触发重渲染。
- 替代:替代类组件的实例变量。
应用场景:表单控制、计数器。
17. React 的 lazy
和 Suspense
如何实现懒加载?
答案解析
React.lazy
动态加载组件,Suspense
提供加载中状态。
- 作用:减少首屏加载体积。
代码示例:
const LazyComponent = React.lazy(() => import("./LazyComponent"));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<LazyComponent />
</Suspense>
);
}
解析:
- 原理:
import()
返回 Promise。 - 构建:Webpack 分割代码块。
- 注意:SSR 需特殊处理。
应用场景:路由组件、弹窗。
18. React 的 useContext
如何优化性能?
答案解析
useContext
使用不当可能导致不必要重渲染,优化方法:
- 拆分 Context:细化数据范围。
- 结合
useMemo
:缓存值。
代码示例:
const CountContext = React.createContext();
function Provider() {
const [count, setCount] = React.useState(0);
const value = React.useMemo(() => ({ count, setCount }), [count]);
return (
<CountContext.Provider value={value}>
<Consumer />
</CountContext.Provider>
);
}
function Consumer() {
const { count } = React.useContext(CountContext);
return <div>{count}</div>;
}
解析:
- 问题:Provider 更新影响所有消费者。
- 优化:稳定引用减少渲染。
应用场景:全局状态优化。
19. React 的 useEffect
如何处理异步操作?
答案解析
useEffect
不直接支持 async,但可包裹异步函数。
- 方法:在 effect 中调用 async 函数。
代码示例:
function DataFetcher() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
const fetchData = async () => {
const result = await apiCall();
setData(result);
};
fetchData();
}, []);
return <div>{data}</div>;
}
解析:
- 清理:返回函数处理取消。
- 注意:避免直接
async () =>
作为 effect。 - 替代:
useAsync
自定义 Hook。
应用场景:API 数据加载。
20. React 的 Fragment
有什么作用?
答案解析
Fragment
允许返回多个子节点,无需额外包裹元素。
- 作用:减少 DOM 层级,优化结构。
代码示例:
function List() {
return (
<React.Fragment>
<li>Item 1</li>
<li>Item 2</li>
</React.Fragment>
);
// 简写: <>...</>
}
解析:
- 替代:替代无意义的
<div>
。 - key:支持
key
属性(如列表)。 - 性能:减少 DOM 操作。
应用场景:列表渲染、条件组。
21. React 的 useLayoutEffect
和 useEffect
有什么区别?
答案解析:
- useEffect:异步执行,DOM 更新后运行。
- useLayoutEffect:同步执行,DOM 更新前运行。
代码示例:
function Example() {
const [width, setWidth] = React.useState(0);
const ref = React.useRef();
React.useLayoutEffect(() => {
setWidth(ref.current.offsetWidth); // 同步获取
}, []);
return <div ref={ref}>Width: {width}</div>;
}
解析:
- 时机:
useLayoutEffect
避免闪烁。 - 性能:
useEffect
不阻塞渲染。 - 选择:布局相关用前者。
应用场景:测量 DOM、动画。
22. React 的 useTransition
如何优化交互?
答案解析
useTransition
(React 18+)标记非紧急更新,优化用户体验。
- 作用:区分紧急和过渡状态更新。
代码示例:
function Search() {
const [query, setQuery] = React.useState("");
const [results, setResults] = React.useState([]);
const [isPending, startTransition] = React.useTransition();
const handleChange = (e) => {
setQuery(e.target.value);
startTransition(() => {
setResults(search(e.target.value)); // 延迟更新
});
};
return (
<>
<input value={query} onChange={handleChange} />
{isPending ? "Loading..." : results.map(r => <div>{r}</div>)}
</>
);
}
解析:
- 效果:输入流畅,搜索延迟。
- Fiber:基于并发渲染。
- 用途:提升响应性。
应用场景:搜索、过滤。
23. React 的 useDeferredValue
有什么作用?
答案解析
useDeferredValue
(React 18+)延迟值的更新,优化复杂渲染。
- 作用:让低优先级任务延迟执行。
代码示例:
function List({ input }) {
const deferredInput = React.useDeferredValue(input);
const items = React.useMemo(() => heavyCompute(deferredInput), [deferredInput]);
return <ul>{items.map(i => <li>{i}</li>)}</ul>;
}
function App() {
const [input, setInput] = React.useState("");
return (
<>
<input value={input} onChange={e => setInput(e.target.value)} />
<List input={input} />
</>
);
}
解析:
- 效果:输入不卡顿,列表稍后更新。
- 对比
useTransition
:更简单,无需显式标记。 - 场景:大数据渲染。
应用场景:实时输入优化。
24. React 的 StrictMode
有什么作用?
答案解析
StrictMode
是开发工具,检测潜在问题。
- 功能:
- 检查不安全的生命周期。
- 警告副作用问题。
- 双次调用 Hooks(React 18)。
代码示例:
function App() {
return (
<React.StrictMode>
<Child />
</React.StrictMode>
);
}
function Child() {
React.useEffect(() => console.log("Effect")); // 打印两次
return <div>Child</div>;
}
解析:
- 目的:暴露 bug,不影响生产。
- 双次调用:模拟卸载后重载。
- 注意:仅开发环境生效。
应用场景:代码健壮性检查。
25. React 的 createPortal
如何实现弹窗?
答案解析
createPortal
将组件渲染到指定 DOM 节点,脱离父组件层级。
- 作用:解决层级和样式冲突。
代码示例:
function Modal({ children }) {
return ReactDOM.createPortal(
<div className="modal">{children}</div>,
document.getElementById("modal-root")
);
}
function App() {
return (
<>
<Modal>Modal Content</Modal>
<div id="modal-root" />
</>
);
}
解析:
- 对比 Teleport:Vue 3 内置,React 需手动。
- 优势:保持事件冒泡。
- 用途:全局组件渲染。
应用场景:弹窗、tooltip。
26. React 的组件设计原则有哪些?
答案解析
React 组件设计遵循以下原则:
- 单一职责:每个组件专注单一功能。
- 可复用性:抽象通用逻辑,减少重复。
- 可组合性:通过 props 和 children 组合组件。
- 状态隔离:状态尽量局部化,避免全局依赖。
代码示例:
function Button({ onClick, children }) {
return <button onClick={onClick}>{children}</button>;
}
function App() {
return (
<Button onClick={() => alert("Clicked")}>Click Me</Button>
);
}
解析:
- 单一职责:
Button
只负责渲染和点击。 - 可复用性:通过
children
定制内容。 - 优化:避免深层嵌套,保持扁平结构。
应用场景:UI 库开发、复杂页面。
27. React 的 useCallback
如何优化子组件渲染?
答案解析
useCallback
缓存函数引用,防止子组件因函数重新创建而重渲染。
- 作用:稳定 props 中的回调函数。
代码示例:
const Child = React.memo(({ onChange }) => {
console.log("Child rendered");
return <input onChange={onChange} />;
});
function Parent() {
const [value, setValue] = React.useState("");
const handleChange = React.useCallback(e => setValue(e.target.value), []);
return <Child onChange={handleChange} />;
}
解析:
- 问题:未缓存的函数每次渲染都不同。
- 解决:
useCallback
确保引用一致。 - 依赖:空数组表示不变,需谨慎选择。
应用场景:表单输入、事件处理。
28. React 的 useMemo
如何优化昂贵计算?
答案解析
useMemo
缓存计算结果,仅在依赖变化时重新计算。
- 作用:避免重复执行性能开销大的操作。
代码示例:
function ExpensiveList({ items }) {
const filtered = React.useMemo(() => {
return items.filter(item => item > 0);
}, [items]);
return <ul>{filtered.map(i => <li>{i}</li>)}</ul>;
}
function App() {
const [items, setItems] = React.useState([1, -1, 2]);
return <ExpensiveList items={items} />;
}
解析:
- 性能:减少不必要过滤。
- 依赖:确保
items
变化时更新。 - 对比
useCallback
:返回值的缓存。
应用场景:大数据过滤、复杂计算。
29. React 的自定义 Hook 如何设计?
答案解析
自定义 Hook 封装可复用逻辑,遵循命名(useXxx
)和 Hooks 规则。
- 原则:
- 逻辑复用。
- 独立性。
- 参数化配置。
代码示例:
function useToggle(initialValue = false) {
const [value, setValue] = React.useState(initialValue);
const toggle = () => setValue(prev => !prev);
return [value, toggle];
}
function App() {
const [isOn, toggle] = useToggle();
return <button onClick={toggle}>{isOn ? "ON" : "OFF"}</button>;
}
解析:
- 复用:多个组件共享切换逻辑。
- 灵活性:支持初始值参数。
- 规则:内部只能调用其他 Hooks。
应用场景:状态管理、工具函数。
30. React 的 useReducer
如何与 Context 结合?
答案解析
useReducer
和 Context 结合,实现类似 Redux 的全局状态管理。
- 步骤:Context 传递状态和 dispatch,
useReducer
更新逻辑。
代码示例:
const CountContext = React.createContext();
function reducer(state, action) {
switch (action.type) {
case "increment": return { count: state.count + 1 };
default: return state;
}
}
function Provider({ children }) {
const [state, dispatch] = React.useReducer(reducer, { count: 0 });
return (
<CountContext.Provider value={
{ state, dispatch }}>
{children}
</CountContext.Provider>
);
}
function Counter() {
const { state, dispatch } = React.useContext(CountContext);
return (
<button onClick={() => dispatch({ type: "increment" })}>
{state.count}
</button>
);
}
function App() {
return (
<Provider>
<Counter />
</Provider>
);
}
解析:
- 优势:集中状态管理,减少 prop drilling。
- 优化:用
useMemo
稳定 value。
应用场景:小型应用全局状态。
31. React 的 useEffect
如何处理事件监听?
答案解析
useEffect
通过添加和清理事件监听器,管理副作用。
- 方法:监听器在挂载时绑定,卸载时移除。
代码示例:
function WindowSize() {
const [size, setSize] = React.useState(window.innerWidth);
React.useEffect(() => {
const handleResize = () => setSize(window.innerWidth);
window.addEventListener("resize", handleResize);
return () => window.removeEventListener("resize", handleResize);
}, []);
return <div>Width: {size}px</div>;
}
解析:
- 清理:防止内存泄漏。
- 依赖:空数组确保只绑定一次。
- 注意:动态事件需更新依赖。
应用场景:窗口大小、滚动监听。
32. React 的 memo
如何自定义比较逻辑?
答案解析
React.memo
支持第二个参数,自定义 props 比较逻辑。
- 作用:替代默认浅比较,处理深层对象。
代码示例:
const Child = React.memo(({ data }) => (
<div>{data.name}</div>
), (prevProps, nextProps) => {
return prevProps.data.name === nextProps.data.name;
});
function Parent() {
const [state, setState] = React.useState({ name: "Alice", age: 25 });
return <Child data={state} />;
}
解析:
- 默认:浅比较只检查引用。
- 自定义:精确控制更新条件。
- 性能:避免复杂比较函数。
应用场景:嵌套对象 props。
33. React 的 useRef
如何保存上一次状态?
答案解析
useRef
保存跨渲染的值,可记录上一次状态。
- 作用:不触发重渲染,追踪历史值。
代码示例:
function Counter() {
const [count, setCount] = React.useState(0);
const prevCountRef = React.useRef();
React.useEffect(() => {
prevCountRef.current = count;
}, [count]);
return (
<div>
<p>Current: {count}, Previous: {prevCountRef.current}</p>
<button onClick={() => setCount(count + 1)}>Add</button>
</div>
);
}
解析:
- 原理:
useRef
持久化存储。 - 替代:类组件的实例变量。
- 注意:初始值为
undefined
。
应用场景:状态变化对比。
34. React 的 useLayoutEffect
如何避免闪烁?
答案解析
useLayoutEffect
在 DOM 更新前同步执行,避免视觉不一致。
- 作用:处理布局相关副作用。
代码示例:
function Position() {
const [pos, setPos] = React.useState(0);
const ref = React.useRef();
React.useLayoutEffect(() => {
const rect = ref.current.getBoundingClientRect();
setPos(rect.top); // 同步更新
}, []);
return <div ref={ref}>Top: {pos}px</div>;
}
解析:
- 对比
useEffect
:后者异步可能闪烁。 - 性能:阻塞渲染,谨慎使用。
- 场景:需要立即测量 DOM。
应用场景:动画初始化、布局计算。
35. React 的 useTransition
如何优化大数据渲染?
答案解析
useTransition
(React 18+)将大数据渲染标记为过渡任务,优先响应用户交互。
- 作用:避免阻塞 UI 线程。
code示例:
function FilterList() {
const [input, setInput] = React.useState("");
const [list, setList] = React.useState([]);
const [isPending, startTransition] = React.useTransition();
const handleChange = (e) => {
setInput(e.target.value);
startTransition(() => {
setList(filterLargeData(e.target.value));
});
};
return (
<>
<input value={input} onChange={handleChange} />
{isPending ? "Loading..." : list.map(i => <div>{i}</div>)}
</>
);
}
解析:
- 效果:输入流畅,列表稍后更新。
- 并发:基于 Fiber 优先级调度。
- 注意:需合理提示加载。
应用场景:实时搜索、大列表。
36. React 的 useDeferredValue
如何与输入框结合?
答案解析
useDeferredValue
延迟输入值更新,优化复杂渲染响应。
- 作用:保持输入流畅,延迟副作用。
code示例:
function Search() {
const [query, setQuery] = React.useState("");
const deferredQuery = React.useDeferredValue(query);
const results = React.useMemo(() => search(deferredQuery), [deferredQuery]);
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} />
<div>{results}</div>
</>
);
}
解析:
- 效果:输入不卡顿,搜索稍后执行。
- 对比
debounce
:React 内部管理。 - 用途:提升用户体验。
应用场景:动态搜索、下拉建议。
37. React 的 Context 如何避免不必要重渲染?
答案解析
Context 的 Provider 更新会导致所有消费者重渲染,优化方法:
- 拆分 Context:隔离变化部分。
- 用
useMemo
:稳定 value。
code示例:
const CountContext = React.createContext();
function Provider() {
const [count, setCount] = React.useState(0);
const value = React.useMemo(() => ({ count }), [count]);
return (
<CountContext.Provider value={value}>
<Consumer />
<button onClick={() => setCount(count + 1)}>Add</button>
</CountContext.Provider>
);
}
const Consumer = React.memo(() => {
const { count } = React.useContext(CountContext);
return <div>{count}</div>;
});
解析:
- 问题:
value
引用变化触发渲染。 - 解决:缓存对象或细化 Context。
- 替代:Redux 或状态提升。
应用场景:全局状态优化。
38. React 的 forwardRef
如何与 Hooks 结合?
答案解析
forwardRef
将 ref 传递给函数组件,结合 Hooks 实现动态控制。
- 作用:暴露 DOM 或自定义方法。
code示例:
const Input = React.forwardRef((props, ref) => {
const inputRef = React.useRef();
React.useImperativeHandle(ref, () => ({
focus: () => inputRef.current.focus(),
clear: () => inputRef.current.value = "",
}));
return <input ref={inputRef} {...props} />;
});
function App() {
const ref = React.useRef();
return (
<>
<Input ref={ref} />
<button onClick={() => ref.current.clear()}>Clear</button>
</>
);
}
解析:
- 灵活性:自定义暴露接口。
- Hooks:
useImperativeHandle
增强。 - 用途:增强组件交互。
应用场景:表单管理、焦点控制。
39. React 的 useEffect
如何模拟类组件生命周期?
答案解析
useEffect
通过依赖数组和清理函数,模拟类组件生命周期:
- componentDidMount:空依赖。
- componentDidUpdate:指定依赖。
- componentWillUnmount:返回清理。
code示例:
function Component() {
const [data, setData] = React.useState(null);
React.useEffect(() => {
console.log("Mounted"); // DidMount
fetchData().then(setData);
return () => console.log("Unmounted"); // WillUnmount
}, []);
React.useEffect(() => {
console.log("Data updated:", data); // DidUpdate
}, [data]);
return <div>{data}</div>;
}
解析:
- 统一性:取代分散的生命周期。
- 注意:依赖需完整声明。
- 调试:避免遗漏清理。
应用场景:组件初始化、销毁。
40. React 的 useCallback
如何与 memo
协同?
答案解析
useCallback
稳定函数引用,与 memo
配合防止子组件重渲染。
- 作用:优化性能,减少不必要更新。
code示例:
const Child = React.memo(({ onClick }) => {
console.log("Child rendered");
return <button onClick={onClick}>Click</button>;
});
function Parent() {
const [count, setCount] = React.useState(0);
const handleClick = React.useCallback(() => console.log("Clicked"), []);
return (
<>
<Child onClick={handleClick} />
<button onClick={() => setCount(count + 1)}>{count}</button>
</>
);
}
解析:
- 协同:
memo
检查 props,useCallback
确保稳定。 - 依赖:空数组表示不变。
- 效果:
count
更新不影响Child
。
应用场景:事件回调优化。
41. React 的 useReducer
如何处理复杂表单?
答案解析
useReducer
通过集中式 reducer 管理表单状态,提升可维护性。
- 优势:状态更新逻辑清晰。
code示例:
const initialState = { name: "", email: "" };
function reducer(state, action) {
switch (action.type) {
case "update": return { ...state, [action.field]: action.value };
default: return state;
}
}
function Form() {
const [state, dispatch] = React.useReducer(reducer, initialState);
return (
<>
<input
value={state.name}
onChange={e => dispatch({ type: "update", field: "name", value: e.target.value })}
/>
<input
value={state.email}
onChange={e => dispatch({ type: "update", field: "email", value: e.target.value })}
/>
</>
);
}
解析:
- 集中:所有更新通过
dispatch
。 - 扩展性:易添加校验、重置。
- 对比
useState
:多字段更简洁。
应用场景:多输入表单。
42. React 的 useMemo
如何优化列表渲染?
答案解析
useMemo
缓存列表数据或组件,减少重复计算和渲染。
- 作用:提升大数据列表性能。
code示例:
function List({ items }) {
const renderedItems = React.useMemo(() => {
return items.map(item => <li key={item.id}>{item.name}</li>);
}, [items]);
return <ul>{renderedItems}</ul>;
}
function App() {
const [items, setItems] = React.useState([{ id: 1, name: "A" }]);
return <List items={items} />;
}
解析:
- 优化:
items
不变时复用结果。 - 注意:确保
key
唯一。 - 搭配:结合
memo
更佳。
应用场景:动态列表、过滤结果。
43. React 的 useContext
如何与 Redux 对比?
答案解析
useContext
和 Redux 都用于状态管理,但适用场景不同:
- useContext:轻量级,适合简单共享。
- Redux:复杂应用,提供中间件和调试工具。
code示例(useContext):
const StateContext = React.createContext();
function App() {
const [state, setState] = React.useState({ count: 0 });
return (
<StateContext.Provider value={
{ state, setState }}>
<Child />
</StateContext.Provider>
);
}
解析:
- useContext:无额外依赖,易上手。
- Redux:支持时间旅行、action 追踪。
- 选择:小型用 Context,大型用 Redux。
应用场景:小型项目 vs 企业级应用。
44. React 的 useEffect
如何处理竞态条件?
答案解析
useEffect
中的异步操作可能导致竞态条件,需通过清理或标志解决。
- 问题:多个请求顺序混乱。
code示例:
function Fetcher({ id }) {
const [data, setData] = React.useState(null);
React.useEffect(() => {
let isMounted = true;
fetchData(id).then(result => {
if (isMounted) setData(result);
});
return () => { isMounted = false; };
}, [id]);
return <div>{data}</div>;
}
解析:
- 清理:标志确保最新请求生效。
- 替代:使用
AbortController
取消请求。 - 效果:避免旧数据覆盖。
应用场景:动态 ID 数据加载。
45. React 的 lazy
如何与路由结合?
答案解析
React.lazy
结合路由实现按需加载,减少首屏体积。
- 步骤:动态导入组件,搭配
Suspense
。
code示例:
import { BrowserRouter, Route, Routes } from "react-router-dom";
const Home = React.lazy(() => import("./Home"));
const About = React.lazy(() => import("./About"));
function App() {
return (
<BrowserRouter>
<Suspense fallback={<div>Loading...</div>}>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Suspense>
</BrowserRouter>
);
}
解析:
- 效果:按路由分割代码。
- 构建:Webpack 自动分包。
- 注意:SSR 需额外配置。
应用场景:SPA 路由优化。