React:Redux 和 localStorage
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
本周,React我一直在研究如何理清states使用Redux和react-redux 传递数据的复杂关系,同时我还研究了如何将 Redux store 存储在localStorage中。
好处
让我们想象这样一个场景:我们有两个组件,一个待办事项列表,用于显示项目并提供一些交互(例如删除),以及一个允许您添加项目的输入表单,这并不是一个罕见的场景。
你可能会创建一个包装组件,其中包含一个状态(包含列表)和一些用于编辑状态的函数,我们可以使用 props 将该状态传递给我们的组件。
这看起来很简单,但假设我们还有另一个页面,它是一个筛选后的列表,比如只显示标记为已完成的项目,那么如何才能访问到原始状态呢?你必须将状态存储在更高层级,以便将其传递给所有需要它的组件。函数也需要向下传递。需要数据的地方越多,这种方法就越复杂。
然而,Redux 创建了一个 store,我们可以从任何组件访问甚至编辑它。需要在应用某个隐蔽的设置面板中查看列表?没问题,直接访问 store 获取即可。是不是更简单?Redux 的确需要一些代码才能上手,但说实话,一旦全部配置完成,向 store 添加新条目和功能就非常容易了。
样板
让我们先把所有常规步骤都解决掉,我创建了 3 个文件夹,src每个文件夹里都包含一个文件index.js。它们分别是reducers,store和actions。
减速器
这里是我们创建商店逻辑的地方。每个商店商品都需要一个文件。我想创建一个列表商店,所以我会向您展示添加商品的逻辑。我们将这个文件命名为list.js
// We pass in a state, which is empty by default
// and an action which we will learn about in the
// actions file
const listReducer = (state = {}, action) => {
// Clone state object
const newState = Object.assign({}, state);
// Look for type set in the actions file
// these types should be as unique as possible
switch (action.type) {
case "LISTITEM_ADD":
// Generate random key and populate with default object.
// Payload is set in the actions file
newState[
Math.random()
.toString(36)
.replace(/[^a-z]+/g, "")
] = {
complete: false,
label: action.payload
};
break;
default:
break;
}
// return the modified state
return newState;
};
export default listReducer;
现在我们来看一下索引文件。索引文件的目的是将所有 reducer 合并成一个易于管理的 reducer。Redux 提供了一个专门combineReducers用于此目的的函数。
import listReducer from "./list";
import { combineReducers } from "redux";
// The key of this object will be the name of the store
const rootReducers = combineReducers({ list: listReducer });
export default rootReducers;
店铺
这就是神奇之处localStorage。只需将这两个函数结合起来,我们就能在会话之间存储所有数据。
import { createStore } from "redux";
import rootReducers from "../reducers";
// convert object to string and store in localStorage
function saveToLocalStorage(state) {
try {
const serialisedState = JSON.stringify(state);
localStorage.setItem("persistantState", serialisedState);
} catch (e) {
console.warn(e);
}
}
// load string from localStarage and convert into an Object
// invalid output must be undefined
function loadFromLocalStorage() {
try {
const serialisedState = localStorage.getItem("persistantState");
if (serialisedState === null) return undefined;
return JSON.parse(serialisedState);
} catch (e) {
console.warn(e);
return undefined;
}
}
// create our store from our rootReducers and use loadFromLocalStorage
// to overwrite any values that we already have saved
const store = createStore(rootReducers, loadFromLocalStorage());
// listen for store changes and use saveToLocalStorage to
// save them to localStorage
store.subscribe(() => saveToLocalStorage(store.getState()));
export default store;
如果您不想存储数据,则需要删除saveToLocalStorageandloadFromLocalStorage函数,还需要删除loadFromLocalStoragefromcreateStore和整store.subscribe行代码。
行动
这里将存放我们的“函数”,我称它们为函数,但它们非常简单。函数会返回一个包含类型和有效载荷的对象,有效载荷就是我们用来指代传入参数的术语。
export const addItem = payload => {
return {
type: "LISTITEM_ADD",
payload
};
};
使用提供商
Provider 由 提供react-redux。它是一个包装组件,我们将其放在 React 的 index 文件中。它看起来应该像这样。
import React from "react";
import ReactDOM from "react-dom";
import store from "./store";
import { Provider } from "react-redux";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
rootElement
);
使用商店
我在文章开头就说过,有很多样板代码需要编写,现在我们终于完成了,终于可以开始使用这个商店了。
使用选择器
useSelector这是redux-react从数据存储中读取数据的一种方式,使用起来非常简单。您必须先导入它,然后就可以像这样使用它了。
import { useSelector } from "react-redux";
// As you see we're getting the whole state
// but we're only returning list which is the
// name we gave it in the reducers file
const list = useSelector(state => state.list);
现在我们可以list在组件中随意使用它了。
使用调度
useDispatch还有一点redux-react。它允许你将一个函数分发到 store。同样,它的使用非常简单,因为之前所有的样板代码都已经完成了繁重的工作。我们需要从 ` actionsand`导入我们想要使用的函数useDispatch。
import { addItem } from "../actions";
import { useDispatch } from "react-redux";
// This stores the dispatch function for using in the component
const dispatch = useDispatch();
// we run the dispatch function containing the addItem function
// As you remember addItem takes a payload and returns an object
// It will now run the reducer
dispatch(addItem(value));
结语
一旦所有样板代码都已清除,跨组件访问数据就变得容易得多,我预见到它将在未来的项目中对我大有帮助。它还有一个额外的好处,那就是跨会话保存变得超级简单!
这周内容有点长,但我们总算完成了。感谢阅读。如果您有任何问题或更正,欢迎在下方留言。
再次感谢🦄🦄💕❤️🧡💛💚🤓🧠
文章来源:https://dev.to/link2twenty/react-redux-and-localstorage-2lih