页面刷新时React Redux状态丢失

时间:2018-09-04 07:36:04

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

在我的React应用中,我有3个组成部分。从第一个组件的按钮开始,我使用链接转到第二个组件。在第二处,我创建一个状态(redux存储),对其进行操作,并在完成操作后通过提交按钮将我重定向到第三处。在第三个组件上,我还看到了状态(通过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);

最后是Battle组件,我首先看到状态但刷新后丢失

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);

5 个答案:

答案 0 :(得分:4)

您可以轻松地将其持久存储在本地存储中。请查看下面的示例。

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(
  // Other reducer
  persistedState,
);

render(
  <Provider store={store}>
    <App/>
  </Provider>,
  document.getElementById('root');
);

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

例如:

import throttle from 'lodash/throttle';

store.subscribe(throttle(() => {
  saveState(store.getState());
}, 1000));

答案 1 :(得分:2)

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

答案 2 :(得分:0)

我对热重装的个人建议是使用React hot loader,这可以防止页面重装并且仅切出更改的块。这意味着您的状态不会在开发时迷路。

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

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

答案 3 :(得分:0)

    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);
}

答案 4 :(得分:0)

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;