前言
- 对于某个页面中的某个组件,很多时候需要其保持一直激活的状态,之前我的博客里面有一篇提到一种缓存策略,就是利用
Route
的children
方法来display
该组件或隐藏该组件。但是这种方式需要借助到Route
组件并且只能缓存整个页面,而不是页面中的部分组件。并且这种缓存单纯的只是在页面上把它的display
变成了block
和none
,仅仅是在路由离开的时候不卸载掉该组件。
- 对此,还有一种思路也可以尝试一下,就是在一个组件离开前去保存它所有的
state
值,等到下次渲染组件的时候把上次卸载钱的state
值还原回来,不就可以使得,组件重新渲染后依然是上一次离开前的状态吗。
实现思路
- 给需要缓存的组件加一层高阶组件,在高阶组件中通过
ref
获取到该组件的实例。
- 在
ComponentDidMount
中通过ref
获取到的实例,调用组件的setState
方法,把缓存的上一次的state
数据注入进去。
- 在
ComponentWillUnmount
中通过ref
获取到的实例,去获取其所有state
的值,并存在缓存中。
代码实现
const keepAlive = (Comp) => {
let cache = {};
return class Alive extends React.Component {
componentDidMount() {
const state = this.comp.state;
this.comp.setState({ ...state, ...cache });
}
componentWillUnmount() {
const state = this.comp.state;
cache = { ...state };
}
render() {
return (
<Comp ref={comp => this.comp = comp} { ...this.props } />
)
}
}
}
import React from 'react';
import keepAlive from 'keep-alive-react';
class Test extends React.Component {
state = {
count: 0
}
render() {
const { count } = this.state;
return (
<div className="Test">
Test
<div>count: {count}</div>
<div onClick={() => {
this.setState({
count: count + 1
})
}}>add</div>
</div>
);
}
}
export default keepAlive(Test);
小结
- 目前该实现方式,暂不能支持函数式组件,函数式组件的状态都是使用的
hooks
写法,而hooks
写法中无法便捷统一的去获取其组件所有的state
值,并且也无法针对函数式组件去拿到该组件内部的引用,导致该思路只能给继承自React.Component
的组件使用。
- 该方法已经发布到
npm
上。直接使用npm i keep-alive-react --save
就可以像示例中一样进行全局引用。