【问题标题】:React Redux state is lost at page refreshReact Redux 状态在页面刷新时丢失
【发布时间】:2019-02-09 04:22:41
【问题描述】:

在我的反应应用程序中,我有 3 个组件。通过一个按钮从第一个组件,我使用链接转到第二个组件。在第 2 次我创建一个状态(redux 存储),对其进行操作,当通过提交按钮完成操作时,我重定向到第 3 个组件。在第三个组件,我也看到了状态(通过 redux chrome 工具),但是当我刷新页面时(更改和保存代码时的 webpack 事情),我失去了状态并得到一个空对象。

这是我的应用程序的结构。

index.js

const store = createStore(
  rootReducer,
  composeWithDevTools(applyMiddleware(thunk))
);

ReactDOM.render(
  <BrowserRouter>
    <Provider store={store}>
      <Route component={App} />
    </Provider>
  </BrowserRouter>,
  document.getElementById("root")
);

App.js

const App = ({ location }) => (
  <Container>
    <Route location={location} path="/" exact component={HomePage} />
    <Route location={location} path="/GameInit" exact component={GameInit} />
    <Route location={location} path="/Battle" exact component={Battle} />
  </Container>
);

App.propTypes = {
  location: PropTypes.shape({
    pathname: PropTypes.string.isRequired
  }).isRequired
};

export default App;

在主页,我有一个链接到 GameInit 的按钮

const HomePage = () => (<Button color="blue" as={Link} to="/GameInit">START GAME</Button>);
export default HomePage;

GameInit 页面看起来像

class GameInit extends Component {
  componentWillMount() {
    const { createNewPlayer} = this.props;
    createNewPlayer();
  }
/* state manipulation till it gets valid */
 palyerIsReady()=>{ history.push("/Battle");}

export default connect(mapStateToProps,{ createNewPlayer})(GameInit);

最后是我第一次看到状态但在刷新时丢失的战斗组件

class Battle extends Component {
  render() {return (/*some stuff*/);}}

Battle.propTypes = {
  players: PropTypes.object.isRequired // eslint-disable-line
};
const mapStateToProps = state => ({
  players: state.players
});
export default connect(mapStateToProps,null)(Battle);

【问题讨论】:

  • 这很自然...
  • @BhojendraRauniyar 和解决方案?
  • 这里不是 Thunk 作为中间件来处理这个问题吗?如果我想将所有内容持久化到本地存储中,为什么还要使用 redux?
  • 否则你可以使用 redux-persist
  • 准备初始状态并通过 createStore(combined, { a: 'horse' }) 传递它。 redux.js.org/recipes/structuringreducers/initializingstate。从我的角度来看,这是原因

标签: reactjs redux react-redux react-router-v4 react-router-dom


【解决方案1】:

您可以使用redux-persist 之类的东西将redux 状态保存到local storage 或 到另一个存储系统。

【讨论】:

    【解决方案2】:

    您可以轻松地将其保存在本地存储中。检查下面的示例。

    const loadState = () => {
      try {
        const serializedState = localStorage.getItem('state');
        if(serializedState === null) {
          return undefined;
        }
        return JSON.parse(serializedState);
      } catch (e) {
        return undefined;
      }
    };
    
    const saveState = (state) => {
      try {
        const serializedState = JSON.stringify(state);
        localStorage.setItem('state', serializedState);
      } catch (e) {
        // Ignore write errors;
      }
    };
    
    const peristedState = loadState();
    
    store.subscribe(() => {
      saveState(store.getState());
    });
    
    const store = createStore(
      persistedState,
      // Others reducers...
    );
    
    render(
      <Provider store={store}>
        <App/>
      </Provider>,
      document.getElementById('root');
    );
    

    序列化是一项昂贵的操作。您应该使用限制功能(如 lodash 实现的功能)来限制保存次数。

    例如:

    import throttle from 'lodash/throttle';
    
    store.subscribe(throttle(() => {
      saveState(store.getState());
    }, 1000));
    

    【讨论】:

    • 这看起来很有说服力。所以不再需要 thunk 了吗?
    • 为了查看 chrome 扩展时的状态,我应该写 composeWithDevTools(persistedState) ?
    • 它不会改变您现有代码的任何内容。 createStore 的第二个参数只是初始状态。您仍然可以添加 thunk 并插入 chrome 扩展。
    • 啊哈,我明白了,非常感谢。我的情况的最佳解决方案:)
    • @Temi'Topsy'Bello 我认为代码有错误,你应该在store声明之后写store.subscribe(...)
    【解决方案3】:

    我个人对热重载的建议是使用这个:React hot loader,这可以防止页面重载并且只切换出改变的块。这意味着您的状态在开发时永远不会丢失。

    它很容易安装。您只需添加一个条目并将您的初始组件包装在 hot 中,您可以从包中获取它。

    如果您需要有关其工作原理的更多信息,我建议您观看创作者的this talk

    【讨论】:

      【解决方案4】:
          import React from "react";
      import ReactDOM from "react-dom";
      import "./index.css";
      import * as serviceWorker from "./serviceWorker";
      import { Provider } from "react-redux";
      import { store } from "./rootReducer";
      import { BrowserRouter } from "react-router-dom";
      
      if (process.env.NODE_ENV === "development" && module.hot) {
        module.hot.accept("./rootReducer", () => {
          const newRootReducer = require("./rootReducer").default;
          store.replaceReducer(newRootReducer);
        });
      }
      
      export type AppDispatch = typeof store.dispatch;
      
      const render = () => {
        const App = require("./App").default;
        ReactDOM.render(
          <Provider store={store}>
            <BrowserRouter>
              <App />
            </BrowserRouter>
          </Provider>,
          document.getElementById("root"),
        );
      };
      
      render();
      
      if (process.env.NODE_ENV === "development" && module.hot) {
        module.hot.accept("./App", render);
      }
      

      【讨论】:

        【解决方案5】:

        Alexender Annic 正确回答:

        // persist store code
        const loadState = () => {
          try {
            const serializedState = localStorage.getItem('state');
            if(serializedState === null) {
              return undefined;
            }
            return JSON.parse(serializedState);
          } catch (e) {
            return undefined;
          }
        };
        
        const saveState = (state) => {
          try {
            const serializedState = JSON.stringify(state);
            localStorage.setItem('state', serializedState);
          } catch (e) {
            // Ignore write errors;
          }
        };
        
        const persistedState = loadState();
        
        // This persistedState is includedat the time of store creation as initial value
        const store = createStore(reducers, persistedState);
        
        // This is actually call every time when store saved
        store.subscribe(() => {
          saveState(store.getState());
        });
        
        
        export default store;
        

        【讨论】:

          猜你喜欢
          • 2018-03-22
          • 2020-04-30
          • 2020-09-21
          • 2018-11-17
          • 1970-01-01
          • 2020-01-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多