React Redux 状态在页面刷新时丢失
Posted
技术标签:
【中文标题】React Redux 状态在页面刷新时丢失【英文标题】:React Redux state is lost at page refresh 【发布时间】: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。从我的角度来看,这是原因 【参考方案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;
【讨论】:
以上是关于React Redux 状态在页面刷新时丢失的主要内容,如果未能解决你的问题,请参考以下文章