javascript - React: redux persistence in local storage
问题描述
I'm trying out persisting data to localstorage with Redux. I just made an array of alphabet letter. Whenever I click the element with the onclick listener, I see the console log statement with a random letter each time but the UI doesn't re-render as it would with a setState() call, until I refresh the page. What am I missing here?
src/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import {createStore} from 'redux';
import myApp from './reducers';
import {loadState, saveState} from './localStorage'
const persistedState = loadState();
const store = createStore(
myApp,
persistedState
);
store.subscribe(() => {
saveState(store.getState());
});
function render () {
ReactDOM.render(<App store={store}/>, document.getElementById('root'));
registerServiceWorker();
}
render();
src/app.js
import React, { Component } from 'react';
import './App.css';
import { switchName } from './actions'
class App extends Component {
constructor(props) {
super(props);
this.store = this.props.store;
}
handleChangeName = () => {
let array = ["a","b","c","d","e","f","g","h","i"];
const data = array[Math.floor(Math.random() * array.length)];
this.store.dispatch(switchName(data));
}
render() {
return (
<div className="App">
<p className="ntro" onClick = {this.handleChangeName} >
Letter: {this.store.getState().name}
</p>
</div>
);
}
}
export default App;
src/localstorage.js
export const loadState = () => {
try {
const serializedState = localStorage.getItem('state');
if (serializedState === null) {
console.log("serialzed state null")
return undefined;
}
return JSON.parse(serializedState);
} catch (err) {
return undefined;
}
};
export const saveState = (state) => {
try {
console.log(state)
const serializedState = JSON.stringify(state);
localStorage.setItem('state', serializedState);
} catch (err) {};
}
src/reducers.js
const initialState = {
name: "nada"
}
export default (state = initialState, action) => {
switch (action.type) {
case "SWITCH_NAME":
return Object.assign({}, state,{
name: action.data
})
default:
return state
}
}
解决方案
您的App
组件没有订阅商店,因此当商店更改时它不会重新渲染(即它只会使用name
从返回的第一个值store.getState()
要修复,您可以使用react-redux
toconnect
到商店而不是将其作为道具传递。
src/index.js
import { Provider } from 'react-redux';
// ...
function render () {
ReactDOM.render(<Provider store={store}><App store={store}/></Provider>, document.getElementById('root'));
registerServiceWorker();
}
src/app.js
import { connect } from 'react-redux'
// ...
class App extends Component {
handleChangeName = () => {
let array = ["a","b","c","d","e","f","g","h","i"];
const data = array[Math.floor(Math.random() * array.length)];
this.props.switchName(data);
}
render() {
return (
<div className="App">
<p className="ntro" onClick = {this.handleChangeName} >
Letter: {this.props.name}
</p>
</div>
);
}
}
// note that `store` is no longer used inside the `App` component
const mapState = state => ({ state.name });
const actions = { switchName };
export default connect(mapState, actions)(App);
或者,您可以render()
在subscribe
回调中添加更多调用src/index.js
// ...
store.subscribe(() => {
saveState(store.getState());
render();
});
function render () {
ReactDOM.render(<App store={store}/>, document.getElementById('root'));
registerServiceWorker();
}
render();
尽管您可能想对registerServiceWorker()
通话做其他事情。
旁注:你试过redux-persist
吗?
推荐阅读
- java - 弹簧数据。使用多个字段进行搜索
- replace - 我怎样才能只留下数字?
- javascript - 在使用元素值作为 JavaScript 中的参数调用函数之前检查元素是否存在的最快方法
- html - 如何设置垂直 HTML 列的宽度?
- javascript - 一个一个地显示javascript项目并且有不同的延迟
- apache - 重新发送 POST 数据后 Apache 挂起
- python - AttributeError:“模块”对象没有属性“存在”
- sql - SQL MAX 函数在多行具有相同值时返回一行
- ios - 如何将 UIKit 框架转换为 SceneKit 节点位置?
- python - QThread 信号发出两次