私の反応アプリには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);
ローカルストレージに簡単に永続化できます。以下の例を確認してください。
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));
redux-persist のようなものを使用して、reduxの状態をlocal storage
または別のストレージシステムに保存できます。
ホットリロードに関する私の個人的なアドバイスは、これを使用することです React hot loader 。これは、開発中に状態が失われることが決してないことを意味します。
インストールはかなり簡単です。エントリを追加し、最初のコンポーネントをhot
でラップするだけで、パッケージから取得できます。
それがどのように機能するかについてさらに情報が必要な場合は、作成者が この講演 を視聴することをお勧めします。
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);
}