前言
- 對於某個頁面中的某個組件,很多時候需要其保持一直激活的狀態,之前我的博客里面有一篇提到一種緩存策略,就是利用
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
就可以像示例中一樣進行全局引用。