以下为React面试高阶篇考察点总结,具体知识点不会太详细,主要梳理面试核心考察点,为面试做准备。
一、React-Router
2.React-Router的核心作用
- SPA导航:在单页面应用中管理不同视图的切换,无需重新加载页面
- URL与组件映射:将URL路径映射到对应的React组件,保持UI和URL同步
- 历史记录管理:支持浏览器历史记录的导航(前进/后退)
2.核心组件与API
1.路由器类型
BrowserRouter
- 使用
HTML5 History API(pushState,replaceState)
保持UI与URL同步
import { BrowserRouter } from 'react-router-dom';
<BrowserRouter>
<App />
</BrowserRouter>
HashRouter
<HashRouter>
<App />
</HashRouter>
2.路由定义
Route:定义路径与组件的映射关系
- 使用URL的hash部分(如/#home),适用于不支持History API的旧浏览器
- v5版本:
<Route path="/users" component={Users} />
- v6版本
<Route path="/users" element={<Users />} />
Routes(v6替代v5的Switch)
- 仅渲染第一个匹配的Route,提升性能
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
2.导航组件
- Link:生成无刷新导航链接
<Link to="/about">关于</Link>
- Navigate(V6替代V5的Redirect):重定向到指定路径
<Route path="/old" element={<Navigate to="/new" />} />
3.版本差异(v5 VS v6)
特性 | v5 | v6 |
---|---|---|
路由匹配 | 顺序匹配所有 Route | 优先精确匹配,使用 Routes |
嵌套路由 | 在子组件中定义嵌套 Route | 直接在父 Route 内嵌套 |
重定向 | Redirect 组件 | Navigate 组件 + replace 属性 |
编程式导航 | useHistory | useNavigate |
路由参数 | useParams 获取 | useParams + 动态路由语法优化 |
常见问题与解决方案
1.如何实现嵌套路由
- v5
<Route path="/users" component={Users}>
<Route path="/users/:id" component={UserDetail} />
</Route>
// Users 组件内部渲染子路由:
{this.props.children}
- v6
<Route path="/users" element={<Users />}>
<Route path=":id" element={<UserDetail />} />
</Route>
// Users 组件使用 `<Outlet />` 渲染子路由:
import { Outlet } from 'react-router-dom';
function Users() {
return (
<div>
<h1>用户列表</h1>
<Outlet />
</div>
);
}
2.如何动态处理路由参数?
// 定义动态路径
<Route path="/users/:userId" element={<UserProfile />} />
// 在组件中获取参数
import { useParams } from 'react-router-dom';
function UserProfile() {
const { userId } = useParams();
return <div>用户ID: {userId}</div>;
}
3.编程式导航的实现
- v5
import { useHistory } from 'react-router-dom';
function Login() {
const history = useHistory();
const handleLogin = () => {
history.push('/dashboard');
};
return <button onClick={handleLogin}>登录</button>;
}
- v6
import { useNavigate } from 'react-router-dom';
function Login() {
const navigate = useNavigate();
const handleLogin = () => {
navigate('/dashboard', { state: { from: '/login' } });
};
return <button onClick={handleLogin}>登录</button>;
}
4.路由守卫
function PrivateRoute({ children }){
const isAuthenticated = useAuth(); // 自定义认证逻辑
return isAuthenticate ? chilren : <Navigate to="/login" />;
}
// 使用方式
<Route
path="/dashbord"
element={
<PrivateRoute>
<Dashboard />
</PrivateRoute>
}
5.处理404页面
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NotFound />} />
</Routes>
5.高级技巧与最佳实践
1.代码分割与懒加载
- 结合
React.lazy
和Suspense
实现按需加载
const Users = React.lazy(() => import('./Users'));
<Route path="/users" element={
<Suspense fallback={<Loading />}>
<Users />
</Suspense>
} />
2.传递状态至路由组件
- 使用state属性传递
navigate('/profile', { state: { userData: data } });
// 在目标组件中获取
const location = useLocation();
const userData = location.state?.userData;
3.使用useRoutes配置式路由(V6)
- 集中管理路由配置
const routes = useRoutes([
{ path: '/', element: <Home /> },
{ path: 'users', element: <Users />, children: [
{ path: ':id', element: <UserDetail /> }
]}
]);
return routes;
6.高频面试题
1.BrowserRouter和HashRouter有什么区别?
- BrowserRouter使用
HTML5 History API
,URL格式为example.com/path
- HashRouter使用
URL Hash(example/#/path)
,兼容旧浏览器但不够美观
2.React-Router V6有哪些重大改进
- 引入Routes代替Switch,提升匹配逻辑
- 嵌套路由配置更简洁,支持相对路径
- 移除Redirect,改用Navigate
- element属性直接传递JSX元素,支持更灵活的组件组合
3.如何实现路由鉴权
- 使用高阶组件或自定义路由组件包裹需要保护的路径,检查用户权限后决定渲染目标组件还是重定向到登录页
4.为什么需要exact属性(V5)
- 确保路径完全匹配。例如,path="/" 没有exact时会匹配所有以/开头的URL。v6中默认精确匹配,无需此属性。
二、性能优化
1.优化核心思路
- 减少不必要的渲染:避免组件因无关状态/props变化而重新渲染
- 降低计算开销:缓存高成本计算和函数引用
- 优化DOM操作:减少实际DOM的无效变更
- 合理加载资源:按需加载关键代码与数据
2.关键优化策略与实现
1.组件渲染控制
- React.memo:缓存函数组件渲染结果
const MemoComponent = React.memo(Component, (prevProps, nextProps) => {
return prevProps.id === nextProps.id; // 自定义比较函数
});
- PureComponent:类组件自动浅比较props/state
class OptimizedComponent extends React.PureComponent {
// 自动实现 shouldComponentUpdate 浅比较
}
- shouldComponentUpdate:手动控制类组件更新
shouldComponentUpdate(nextProps, nextState) {
return this.props.data.id !== nextProps.data.id; // 精准控制更新条件
}
2.高效数据管理
- useMemo:缓存复杂计算结果
const processedData = useMemo(() => transformData(rawData), [rawData]);
- useCallback:稳定函数引用
const handleClick = useCallback(() => {
submitData(id);
}, [id]); // id 变化时生成新函数
- 状态结构优化:扁平化数据,避免深层嵌套
// ❌ 避免深层嵌套
const [data, setData] = useState({ user: { profile: { name: '' } } });
// ✅ 拆分为独立状态
const [userName, setUserName] = useState('');
3.列表渲染优化
- key属性优化:使用唯一稳定标识
{items.map(item => (
<ListItem key={item.id} data={item} /> // 避免使用索引作为 key
))}
- 虚拟列表技术:使用react-window实现
import { FixedSizeList as List } from 'react-window';
<List height={600} itemSize={35} itemCount={1000}>
{({ index, style }) => <div style={style}>Row {index}</div>}
</List>
4.资源加载优化
- 代码分割:动态加载非关键组件
const LazyComponent = React.lazy(() => import('./HeavyComponent'));
<Suspense fallback={<Spinner />}>
<LazyComponent />
</Suspense>
- 图片懒加载:使用
Intersection Observer
const LazyImage = ({ src }) => {
const imageRef = useRef();
useEffect(() => {
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting){
imgRef.current.src = src;
observer.unobserve(imgRef.current);
}
});
observer.observe(imgRef.current);
return () => observer.disconnect();
}, []);
return <img ref={imgRef} alt="Lazy loaded" />;
}
3.性能分析工具
1. React DevTools Profiler
- 记录组件渲染耗时
- 查看渲染原因
2. Chorme Perfomance面板
- 分析JavaScript执行耗时
- 识别长任务(Long Tasks)
3. Lighthouse审计
- 综合评估性性能指标(FCP,TTI,TBT)
- 获取优化建议
4.高级优化技术
1.并发模式优化(React18+)
- 自动批处理:合并多个状态更新
// React 18 前:setCount + setValue 触发两次渲染
// React 18:自动合并为一次渲染
const handleClick = () => {
setCount(c => c + 1);
setValue(v => v + 1);
};
- useTransition:区分紧急/非紧急更新
const [isPending, startTransition] = useTransition();
const handleSearch = (query) => {
startTransition(() => {
setSearchQuery(query); // 标记为非紧急更新
});
};
2.服务端渲染优化
- 流式SSR:分块传输HTML
// Next.js示例
export async function getServerSideProps() {
return {
props: { data: await fetchData() },
};
}
- 静态生成:预渲染静态页面
export async function getStaticProps() {
return { props: { /***/ }, recalidate: 60 }; // ISR 增量静态再生
}
5.常见性能陷阱与方案
问题 | 解决方案 |
---|---|
不必要的 Context 更新 | 拆分多个 Context,使用 useMemo 缓存 Provider 值 |
过度使用 useMemo | 仅对高开销计算使用,避免对小计算进行不必要的缓存 |
内存泄漏 | 及时清理定时器、事件监听器、订阅等副作用 |
大状态对象更新 | 使用 Immer 实现不可变更新,避免深拷贝性能问题 |
6.性能优化黄金法则
- 优先解决关键瓶颈:使用Profiler定位主要性能
- 避免过早优化:在出现可测量的性能问题后再实施优化
- 保持组件简单:单一职责组件更易优化
- 渐进增强:优先优化首屏关键路径,再处理次要内容
三、高级特性
1.错误边界
1.定义与作用
- 错误边界是React中的一种特殊类组件,用于
捕获其子组件树中发生的JavaScript错误
,防止这些错误导致整个应用崩溃。通过错误边界,开发者可以优雅地处理错误,并展示降级UI以提升用户体验
2.实现方式
错误边界必须使用类组件实现,并定义以下两个生命周期方法之一(或两者):
static getDerivedStateFromError(error)
- 作用:捕获子组件抛出的错误,返回一个状态对象来更新组件状态
- 触发时机:渲染阶段(Render Phase)
- 返回值:必须返回一个对象用于更新state,以控制是否显示降级UI
2.componentDidCatch(error, errorInfo)
- 作用:记录错误信息(如发送至监控平台)
- 触发时机:提交阶段(Commit Phase)
- 参数:
- error:抛出的错误对象
- errorInfo:包含组件栈信息的对象(componentStack)
class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError(error) {
return { hasError: true }; // 更新状态以显示降级UI
}
componentDidCatch(error, errorInfo) {
logErrorToService(error, errorInfo); // 上报错误
}
render() {
if (this.state.hasError) {
return <h1>Oops! Something went wrong.</h1>;
}
return this.props.children; // 正常渲染子组件
}
}
3.使用场景
1.包裹高风险组件
<ErrorBoundary>
<UnstableComponent />
</ErrorBoundary>
2.全局兜底错误处理
// 在根组件外层包裹错误边界
<ErrorBoundary>
<App />
</ErrorBoundary>
4.错误边界的限制
可捕获的错误类型 | 无法捕获的错误类型 |
---|---|
子组件渲染期间的错误 | 事件处理器中的错误(需手动 try/catch ) |
生命周期方法中的错误 | 异步代码(如 setTimeout 、fetch ) |
构造函数中的错误 | 服务端渲染(SSR)的错误 |
子组件错误边界未处理的错误 | 错误边界自身抛出的错误 |
5.最佳实践
1.避免滥用
- 仅在关键组件或模块使用,而非整个组件
2.组合使用
- 多层错误边界实现局部错误隔离
<ErrorBoundary>
<Header />
<ErrorBoundary>
<MainContent />
</ErrorBoundary>
<Footer />
</ErrorBoundary>
3.try/catch互补
- 错误边界处理渲染错误
- try/catch处理事件处理器、异步代码错误
function MyComponent() {
const handleClick = () => {
try {
// 可能抛出错误的操作
} catch (error) {
logError(error);
}
};
return <button onClick={handleClick}>Click</button>;
}
6.高频面试题
1.函数式组件能否作为错误边界?
- 不能。错误边界必须通过类组件的生命周期方法实现,函数式组件需包裹在类组件的错误边界中
2.错误边界可以捕获哪些阶段的错误?
- 仅捕获渲染阶段(如render、constructor、生命周期方法)的错误,无法捕捉提交阶段(如DOM操作)或异步代码中的错误
3.如何测试错误边界?
- 测试中模拟子组件抛出错误
- 验证错误边界是否显示降级UI
- 检查错误是否正确上报
// 使用 Jest 和 React Testing Library
test('ErrorBoundary shows fallback UI on error', () => {
const ErrorComponent = () => {
throw new Error('Test error');
};
const { getByText } = render(
<ErrorBoundary>
<ErrorComponent />
</ErrorBoundary>
);
expect(getByText('Oops! Something went wrong.')).toBeInTheDocument();
});
4.错误边界如何处理自身错误?
- 错误边界自身的错误会冒泡到上一层的错误边界。若没有父级边界,则导致整个应用崩溃
2.高阶组件
1.定义
高阶组件(Higher-Order Component)是React中用于复用组件逻辑的一种高级技巧。它是一个函数,接受一个组件作为参数,并返回一个新的增强组件。HOC本身不是组件,而是一个组件工厂函数
2.HOC的核心作用
- 逻辑复用:抽离多个组件的公共逻辑(如数据获取,权限控制)
- 增强组件能力:为组件注入额外的props或扩展生命周期行为
- 代码解耦:将业务逻辑与UI组件分离,提升可维护性
3.HOC的实现
1.属性代理(Props Proxy)
- 特点:HOC包裹目标组件,通过props传递数据或方法
function withLogging(wrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log('Component is mounted:', WrappedComponent.name);
}
render() {
// 透传所有的props到被包裹的组件
return <WrappedComponent {...this.props} />;
}
}
}
// 使用
const EnhancedComponent = withLogging(MyComponent);
2.反向继承(Inheritance Inversion)
- 特点:通过继承目标组件,控制其渲染流程(较少使用)
function withEnhancement(WrappedComponent) {
return class extends WrappedComponent {
render() {
// 可修改原组件的渲染结果
const elements = supoer.render();
return React.cloneElement(elements, { newPorps: 'value' });
}
}
}
// 使用
const EnhancedComponent = withEnhancement(MyComponent);
4.HOC应用场景
场景 | 示例 HOC | 功能 |
---|---|---|
权限控制 | withAuth | 检查用户权限,未登录则跳转 |
数据请求 | withFetchData | 统一处理 API 请求与状态管理 |
UI 功能增强 | withHover /withClickOutside | 添加悬停或点击外部关闭功能 |
状态管理 | Redux connect | 连接组件与 Redux Store |
5.注意事项
1.不要修改原始组件
- 使用组合而非继承,避免直接修改原始组件的原型
2.透传无关props
- 确保HOC传递所有与自身无关的props到被包裹组件
render() {
const { extraProp, ...restProps } = this.props;
return <WrappedComponent {...restProps} />;
}
3.处理静态方法
- 使用
hoist-non-react-statics
复制静态方法到新组件
npm install hoist-non-react-statics
import hoistNonReactStatic from 'hoist-non-react-statics';
function withEnhancement(WrappedComponent) {
class EnhancedComponent extends React.Component { /* ... */ }
hoistNonReactStatic(EnhancedComponent, WrappedComponent);
return EnhancedComponent;
}
4.Ref传递问题
- 使用
React.forwardRef
转发Ref到被包裹组件
function withRefForwarding(WrappedComponent) {
class EnhancedComponent extends React.Componnet {
render() {
const { forwardedRef, ...resetProps } = this.props;
return <WrappedComponent ref={forwardedRef} {...resetProps} />;
}
}
return React.forwardRef((props, ref) => (
<EnhancedComponent forwardedRef={ref} {...props} />;
))
}
6.HOC和Hooks对比
维度 | HOC | Hooks |
---|---|---|
适用组件类型 | 类组件/函数组件 | 仅函数组件 |
逻辑复用方式 | 包裹组件,形成组件树层级 | 在组件内部直接调用 Hook 函数 |
代码组织 | 可能引入多层嵌套,可读性下降 | 扁平化逻辑,易于追踪数据流 |
性能影响 | 可能因层级嵌套导致不必要的渲染 | 依赖数组精准控制更新 |
学习曲线 | 需理解高阶函数和组件组合 | 需掌握闭包和依赖数组规则 |
7.高频面试题
1.HOC的优缺点
-
优点:
- 跨组件复用逻辑,减少代码冗余
- 适用于类组件,兼顾旧项目
-
缺点:
- 组件层级嵌套过深,调试困难
- 需处理静态方法和Ref传递
- 可能引发props命名冲突
2.如何避免HOC的props命名冲突?
- 使用命名空间或特点前缀
<WrappedComponent hocData={data} {...restProps} />
- 在HOC中过滤专属props
render() {
const { hocProp, ...passThroughProps } = this.props;
return <WrappedComponent {...passThroughProps} />;
}
3.HOC在React生态的典型应用有哪些?
- Redux:
connect(mapStateToProps, mapDispatchToProps)(Component)
- React Router:
withRouter(Component)
- Material-UI:
whithStyle(styles)(Component)
4.HOC是否会导致性能问题?如何优化?
- 问题:每次父组件渲染时创建新的HOC实例,导致子组件重新挂载
- 优化:在组件外部定义HOC,而非在render方法中动态创建
// ❌ 错误:在 render 中创建 HOC
function Parent() {
const HocComponent = withLogging(Child);
return <HocComponent />;
}
// ✅ 正确:在外部定义 HOC
const EnhancedChild = withLogging(Child);
function Parent() {
return <EnhancedChild />;
}
3.服务端渲染方案
1.核心优势
- SEO友好:爬虫直接解析服务端返回的HTML,提升搜索引擎排名
- 首屏性能优化:减少客户端渲染的白屏时间,提升用户体验
- 兼容性保障:确保低端设备或禁用JavaScript的环境下基础内容可访问
2.主流SSR方案对比
方案 | 特点 | 适用场景 |
---|---|---|
Next.js | 开箱即用、约定式路由、支持 SSG/SSR/ISR | 全栈应用、SEO 要求高的项目 |
Gatsby | 基于 GraphQL 的静态站点生成(SSG)、插件生态丰富 | 内容型网站(博客、文档) |
自定义 SSR | 灵活控制渲染流程、深度定制化 | 复杂企业级应用、特殊架构需求 |
React Server Components | 混合渲染(服务端/客户端组件结合)、减少客户端 JS 体积 | 动态内容与静态内容混合的场景 |
3.Next.js实现SSR深度解析
1.页面级SSR
使用getServerSideProps
在每次请求时生成页面
export async function getServerSideProps(context) {
const data = await fetchData(context.data.id);
return { props: { data } }; // 传递给页面组件
}
function Page({ data }) {
return <div>{data}</div>;
}
2.增量静态再生(ISR)
结合静态生成与按需更新
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
revalidate: 60 // 最多每60秒重新生成一次
};
}
3.客户端水合(Hydration)
自动处理服务端与客户端渲染链接
// 服务端生成HTML
import { renderToString } from 'react-dom/server';
const html = renderToString(<App />);
// 客户端激活
import { hydrateRoot } from 'react-dom/client';
hydrateRoot(document.getElementById('root'), <App />);
4.自定义SSR实现步骤
1.项目结构配置
# 分离客户端和服务端入口
- src/
- client/
- index.js # 客户端入口
- server/
- index.js # 服务端入口
2.Webpack多环境配置
// webpack.client.config.js
module.export = {
entry: './src/client/index.js',
output: {
filename: 'client-bundle.js',
path: path.resolve(__dirname, 'dist'),
}
};
// webpack.server.config.js
module.exports = {
entry: './src/server/index.js',
target: 'node',
output: {
filename: 'server-boudle.js',
path: path.resolve(__dirname, 'dist'),
}
};
3.服务端渲染核心逻辑
import express from 'express';
import React from 'react';
import { renderToString } from 'react-dom/server';
import App from '../shared/App';
const app = express();
app.get('*', (req, res) => {
const html = renderToString(<App />);
res.send(`
<!DOCTYPE html>
<html>
<head>
<title>SSR App</title>
</head>
<body>
<div id="root">${html}</div>
<script src="/client-bundle.js"></script>
</body>
</html>
`);
});
4.数据预取和状态同步
// 服务端数据获取
const fetchData = async () => {
const res = await fetch('https://api.example.com/data');
return res.json();
};
// 客户端同步状态
window.__INITIAL_STATE__ = serverData;
// 客户端入口
const initialState = window.__INITIAL_STATE__;
const store = configureStore(initialState);
hydrateRoot(document.getElementById('root'), <App store={store} />);
5.性能优化策略
1.缓存机制
// 使用 LRU 缓存渲染结果
const microCache = new LRU({
max: 100,
maxAge: 1000 * 60 // 1分钟缓存
});
app.get('*', (req, res) => {
const cachedHtml = microCache.get(req.url);
if (cachedHtml) return res.send(cachedHtml);
const html = renderToString(<App />);
microCache.set(req.url, html);
res.send(html);
});
2.流式渲染
import { renderToPipeableStream } from 'react-dom/server';
app.use((req, res) => {
const stream = renderToPipeableStream(<App />, {
onShellReady() {
res.setHeader('Content-type', 'text/html');
stream.pipe(res);
}
});
});
3.代码分割
// 使用 @loadable/component
import loadable from '@loadable/component';
const LazyComponent = loadable(() => import('./HeavyComponent'));
// 服务端处理
import { ChunkExtractor } from '@loadable/server';
const extractor = new ChunkExtractor({ statsFile: 'dist/loadable-stats.json' });
const jsx = extractor.collectChunks(<App />);
const html = renderToString(jsx);
const scriptTags = extractor.getScriptTags(); // 插入客户端脚本
6.常见问题与解决方案
问题 | 解决方案 |
---|---|
客户端-服务端状态不一致 | 使用 Redux 或 Context API 同步初始化状态 |
window 未定义错误 | 通过条件判断限制客户端专用代码执行:if (typeof window !== 'undefined') |
样式闪烁(FOUC) | 使用 isomorphic-style-loader 提取服务端样式到 <style> 标签 |
内存泄漏 | 监控服务器内存使用,使用 --max-old-space-size 调整 Node.js 内存限制 |
4.React18+新特性
1.并发渲染
React 18的核心更新是引入并发渲染能力,允许React在渲染过程中中断并优先处理更高优先级的任务(比如用户输入),从而提升响应速度。
关键机制
- 时间切片:将渲染任务拆分成小块,避免长时间阻塞主线程
- 优先级调度:用户交互(如点击)优先于数据更新(如API响应)
相关API
startTransition
:标记非紧急更新,可被高优先级任务打断
import { startTransition } from 'react';
const handleSearch = (query) => {
startTransition(() => {
setSearchQuery(query); // 非紧急更新
});
};
useTransition
:跟踪过渡状态,显示加载指示
const [isPending, startTransition] = useTransition();
return (
<button onClick={() => startTransition(handleClick)}>
{isPending ? '加载中...' : '提交'}
</button>
);
2.自动批处理
React 18默认将多次状态更新合并为单次渲染,减少不必要的重复渲染
更新场景对比
场景 | React 17 及之前 | React 18 |
---|---|---|
事件处理器中的更新 | 批量处理 | 批量处理 |
setTimeout/Promise 中的更新 | 不批量处理 | 批量处理 |
强制同步更新
import { flushSync } from 'react-dom';
flushSync(() => {
setCount(c => c + 1); // 立即同步渲染
});
3.流式服务端渲染
通过分块传输HTML和选择性水合,显著提升服务端渲染性能
核心改进
- 流式传输:服务器逐步发送HTML到客户端,缩短首屏时间
- 并行水合:客户端在接收HTML时逐步激活交互功能,无需等待全部内容加载
import { renderToPipeableStream } from 'react-dom/server';
app.get('/', (req, res) => {
const stream = renderToPipeableStream(<App />, {
onShellReady() {
res.setHeader('Content-type', 'text/html');
stream.pipe(res);
},
bootstrapScripts: ['/main.js'] // 客户端脚本
});
});
4.新根API与严格模式增强
1.新根API createRoot
替换原有的ReactDOM.render
,启用并发功能
// React 17
ReactDOM.render(<App />, document.getElementById('root'));
// React 18
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
2.严格模式
- 模拟卸载-挂载:开发环境下组件挂载后立即卸载再重新挂载,检测副作用清理问题
- 重复渲染检测:故意双调用组件函数和Hook,暴露潜在副作用
5.新Hook与API
1.useId
- 生成唯一ID,解决服务端与客户端ID不一致的问题
const id = useId(); // 生成如 :r1: 的稳定 ID
return <label htmlFor={id}>用户名</label>;
2.useDeferredValue
- 延迟更新非关键UI,保持高优先级交互流程
const deferredQuery = useDeferredValue(query);
return <SearchResults query={deferredQuery} />;
3.useSyncExternalStore
- 简化外部状态库(如Redux)集成,避免并发渲染下的撕裂问题
const state = useSyncExternalStore(store.subscribe, store.getState);
6.改进的Suspense功能
- 支持在SSR中与流式渲染结合,优化体验
<Suspense fallback={<Spinner />}>
<Comments /> {/* 异步加载的组件 */}
</Suspense>
以上是React面试题的高阶篇内容,如有错误欢迎评论区指正。