字
字节笔记本
2026年2月22日
React Keep Alive - 组件状态保持方案
本文介绍 react-keep-alive,一个用于 React 应用的组件状态保持库。它能够帮助开发者在组件切换时保持状态,避免重复渲染,特别适用于列表页到详情页的场景。
项目简介
react-keep-alive 是一个开源的 React 组件缓存库,由 StructureBuilder 组织开发维护。该项目在 GitHub 上已获得超过 1000 stars,使用 TypeScript 编写,提供了类似 Vue keep-alive 的功能。
该库的核心价值在于解决 React 应用中组件卸载后状态丢失的问题。当你从列表页进入详情页再返回时,列表页的状态(滚动位置、筛选条件等)能够被完整保留。
核心特性
- 框架无关:不基于 React Router,可在任何需要缓存的地方使用
- 简单易用:使用
<KeepAlive>组件轻松包装需要缓存的组件 - 动画支持:不使用
display: none | block控制,支持过渡动画 - Hooks 支持:完全兼容最新的 React Hooks
- 手动控制:可手动控制组件是否需要保持活力
- 生命周期扩展:提供
componentDidActivate和componentWillUnactivate生命周期
技术栈
- React:16.3+(使用 Hooks 需 16.8+)
- TypeScript:完整类型支持
- React Portals:使用
React.createPortalAPI 实现缓存机制
安装指南
前置要求
- React >= 16.3
- React DOM >= 16.3
安装步骤
bash
# 使用 npm 安装
npm install --save react-keep-alive
# 或使用 yarn
yarn add react-keep-alive
# 或使用 pnpm
pnpm add react-keep-alive快速开始
基础用法
javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, KeepAlive } from 'react-keep-alive';
import Test from './views/Test';
ReactDOM.render(
<Provider>
<KeepAlive name="Test">
<Test />
</KeepAlive>
</Provider>,
document.getElementById('root'),
);结合 React Router 使用
javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { Provider, KeepAlive } from 'react-keep-alive';
class One extends React.Component {
render() {
return <div>This is One.</div>;
}
}
class App extends React.Component {
render() {
return (
<div>
<Switch>
<Route path="/one">
<KeepAlive name="One">
<One />
</KeepAlive>
</Route>
</Switch>
</div>
);
}
}
ReactDOM.render(
<Router>
<Provider>
<App />
</Provider>
</Router>,
document.getElementById('root'),
);使用示例
场景 1:使用 include 属性控制缓存
javascript
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { Provider, KeepAlive } from 'react-keep-alive';
class One extends React.Component {
render() {
return <div>This is One.</div>;
}
}
class App extends React.Component {
render() {
return (
<div>
<Switch>
<Route path="/one">
<KeepAlive name="One">
<One />
</KeepAlive>
</Route>
</Switch>
</div>
);
}
}
ReactDOM.render(
<Router>
<Provider include="One">
<App />
</Provider>
</Router>,
document.getElementById('root'),
);场景 2:使用 bindLifecycle 高阶组件
javascript
import React from 'react';
import { bindLifecycle } from 'react-keep-alive';
@bindLifecycle
class Test extends React.Component {
componentDidActivate() {
console.log('组件被激活');
}
componentWillUnactivate() {
console.log('组件将被取消激活');
}
render() {
return <div>This is Test.</div>;
}
}场景 3:使用 useKeepAliveEffect Hook
javascript
import React from 'react';
import { useKeepAliveEffect } from 'react-keep-alive';
function Test() {
useKeepAliveEffect(() => {
console.log('mounted');
return () => {
console.log('unmounted');
};
});
return <div>This is Test.</div>;
}API 参考
Provider
应用程序的根组件,用于存储缓存的组件。
Props
| 属性 | 类型 | 说明 |
|---|---|---|
| include | string | string[] | RegExp | 只缓存匹配的组件 |
| exclude | string | string[] | RegExp | 不缓存匹配的组件 |
| max | number | 最大缓存数量(v2.5.2+) |
KeepAlive
用于包装需要缓存的组件。
Props
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| name | string | 是 | 唯一标识符 |
| disabled | boolean | 否 | 是否禁用缓存 |
| extra | any | 否 | 额外数据(v2.0.1+) |
bindLifecycle
高阶组件,为被包装组件添加正确的生命周期。
useKeepAliveEffect
Hook,在组件进入和离开时触发,替代 useEffect。
注意事项
- DOM 要求:
<KeepAlive>包裹的组件内部最外层必须有一个真实的 DOM 标签 - React Router 版本:如果使用 React Router,需要确保是最新版本以兼容 new Context API
- 唯一 name:同一
<Provider>下的所有<KeepAlive>的name必须唯一 - 生命周期:如需使用生命周期,请将组件包装在
bindLifecycle中
项目链接
分享: