将manualPersist设置为true时组件不会渲染

问题描述 投票:0回答:1

来自

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
组件不会渲染。浏览器控制台中没有错误日志。会发生什么?我的理解是这个配置是为了手动持久化状态。所以我想在单击按钮时保持状态。

堆栈闪电战

reactjs typescript redux redux-persist
1个回答
0
投票

当未使用

manualPersist
选项并且应用程序启动时,您可以看到应用程序安装时调度到商店的
persist/PERSIST
persist/REHYDRATE
操作。

enter image description here

但是当您指定此选项时,它们就不是了。

enter image description here

似乎

PersistGate
在商店更新之前不会呈现应用程序 UI。

请参阅 PersistGate 自述文件

PersistGate
延迟应用程序 UI 的渲染,直到您的 持久状态已被检索并保存到 redux。

作为测试,您可以在 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。
    

© www.soinside.com 2019 - 2024. All rights reserved.