来自
redux-persist
v6.0.0 文档:persistStore(store, [config, callback])
如果您想避免在调用
后立即开始持久化,请设置选项persistStore
。示例:manualPersist
然后可以使用{ manualPersist: true }
在任意点开始持久化。如果在进行peristor.persist()
调用时您的存储尚未准备好,您通常需要执行此操作。persistStore
尝试使用
manualPersist
配置:
store.ts
:
import { combineReducers, configureStore } from '@reduxjs/toolkit';
import { PersistorOptions, persistReducer, persistStore } from 'redux-persist';
import storage from 'redux-persist/lib/storage';
import { testSlice } from './testSlice';
const rootReducer = combineReducers({
test: testSlice.reducer,
});
const presistedReducer = persistReducer(
{
key: 'root',
storage,
},
rootReducer
);
export const store = configureStore({
reducer: presistedReducer,
});
export const persistor = persistStore(store, {
manualPersist: true,
} as PersistorOptions);
main.tsx
:
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import App from './App';
import './index.css';
import { PersistGate } from 'redux-persist/integration/react';
import { persistor, store } from './store';
ReactDOM.createRoot(document.getElementById('root')!).render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
App.tsx
:
import { persistor } from './store';
import './App.css';
function App() {
return (
<div>
<button
type="button"
onClick={() => {
persistor.persist();
}}
>
persist
</button>
</div>
);
}
export default App;
设置
<App/>
时,manualPersist: true
组件不会渲染。浏览器控制台中没有错误日志。会发生什么?我的理解是这个配置是为了手动持久化状态。所以我想在单击按钮时保持状态。
当未使用
manualPersist
选项并且应用程序启动时,您可以看到应用程序安装时调度到商店的 persist/PERSIST
和 persist/REHYDRATE
操作。
但是当您指定此选项时,它们就不是了。
似乎
PersistGate
在商店更新之前不会呈现应用程序 UI。
请参阅 PersistGate 自述文件:
延迟应用程序 UI 的渲染,直到您的 持久状态已被检索并保存到 redux。PersistGate
作为测试,您可以在 PersistGate
外部渲染按钮元素,以查看按钮是否渲染,但应用程序 UI 不会渲染,直到您单击按钮并持久保存并填充商店。
ReactDOM.createRoot(document.getElementById('root')!).render(
<Provider store={store}>
<button
type="button"
onClick={() => {
persistor.persist();
}}
>
persist
</button>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>
);
单击按钮时,您将看到 localStorage 更新了存储值,持久化器被引导,存储被更新,然后呈现应用程序 UI。
PersistGate
订阅
persistor
并等待它在呈现应用程序 UI 之前被引导。源代码
componentDidMount() {
this._unsubscribe = this.props.persistor.subscribe(
this.handlePersistorState
)
this.handlePersistorState()
}
handlePersistorState = () => {
const { persistor } = this.props
let { bootstrapped } = persistor.getState()
if (bootstrapped) {
if (this.props.onBeforeLift) {
Promise.resolve(this.props.onBeforeLift())
.finally(() => this.setState({ bootstrapped: true }))
} else {
this.setState({ bootstrapped: true })
}
this._unsubscribe && this._unsubscribe()
}
}
...
render() {
if (process.env.NODE_ENV !== 'production') {
if (typeof this.props.children === 'function' && this.props.loading)
console.error(
'redux-persist: PersistGate expects either a function child or loading prop, but not both. The loading prop will be ignored.'
)
}
if (typeof this.props.children === 'function') {
return this.props.children(this.state.bootstrapped)
}
return this.state.bootstrapped ? this.props.children : this.props.loading
}
如果目标是简单地延迟渲染 UI,直到存储/等准备就绪,那么似乎意图是作为应用程序安装/引导流程的一部分以编程方式调用
persistor.persist()
,而不是作为某些手动异步 UI 事件,例如就像用户单击按钮一样。
一旦调用persistor.persist()
,看起来就会发生正常的“自动魔法”状态持续。
如果目标只是手动持久化,那么您的代码似乎需要调用persistor.persist()
来持久化并补充存储,然后立即调用
persistor.pause()
暂停自动持久化状态更新,以便 UI 可以调用 persistor.flush
手动将状态刷新到 localStorage。