web-dev-qa-db-ja.com

Reactページ更新時にRedux状態が失われる

私の反応アプリには3つのコンポーネントがあります。ボタンで最初のコンポーネントから、リンクを使用して2番目のコンポーネントに移動します。 2番目に状態(reduxストア)を作成し、それを操作します。ボタンを送信して操作が完了したら、3番目のコンポーネントにリダイレクトします。 3番目のコンポーネントでは、(redux chrome tool)によって)状態も表示されますが、ここでページを更新すると(コードが変更されて保存されたときの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;

ここHomePageには、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);
4
Amir-Mousavi

ローカルストレージに簡単に永続化できます。以下の例を確認してください。

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));
12
Alexandre Annic

redux-persist のようなものを使用して、reduxの状態をlocal storageまたは別のストレージシステムに保存できます。

3

ホットリロードに関する私の個人的なアドバイスは、これを使用することです React hot loader 。これは、開発中に状態が失われることが決してないことを意味します。

インストールはかなり簡単です。エントリを追加し、最初のコンポーネントをhotでラップするだけで、パッケージから取得できます。

それがどのように機能するかについてさらに情報が必要な場合は、作成者が この講演 を視聴することをお勧めします。

1
jovi De Croock
    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);
}
0