发布于 2026-01-06 6 阅读
0

React:Redux 和 localStorage DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

React:Redux 和 localStorage

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

本周,React我一直在研究如何理清states使用Reduxreact-redux 传递数据的复杂关系,同时我还研究了如何将 Redux store 存储在localStorage中。

好处

让我们想象这样一个场景:我们有两个组件,一个待办事项列表,用于显示项目并提供一些交互(例如删除),以及一个允许您添加项目的输入表单,这并不是一个罕见的场景。

你可能会创建一个包装组件,其中包含一个状态(包含列表)和一些用于编辑状态的函数,我们可以使用 props 将该状态传递给我们的组件。

这看起来很简单,但假设我们还有另一个页面,它是一个筛选后的列表,比如只显示标记为已完成的项目,那么如何才能访问到原始状态呢?你必须将状态存储在更高层级,以便将其传递给所有需要它的组件。函数也需要向下传递。需要数据的地方越多,这种方法就越复杂。

然而,Redux 创建了一个 store,我们可以从任何组件访问甚至编辑它。需要在应用某个隐蔽的设置面板中查看列表?没问题,直接访问 store 获取即可。是不是更简单?Redux 的确需要一些代码才能上手,但说实话,一旦全部配置完成,向 store 添加新条目和功能就非常容易了。

样板

让我们先把所有常规步骤都解决掉,我创建了 3 个文件夹,src每个文件夹里都包含一个文件index.js。它们分别是reducersstoreactions

减速器

这里是我们创建商店逻辑的地方。每个商店商品都需要一个文件。我想创建一个列表商店,所以我会向您展示添加商品的逻辑。我们将这个文件命名为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;
Enter fullscreen mode Exit fullscreen mode

现在我们来看一下索引文件。索引文件的目的是将所有 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;
Enter fullscreen mode Exit fullscreen mode

店铺

这就是神奇之处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;
Enter fullscreen mode Exit fullscreen mode

如果您不想存储数据,则需要删除saveToLocalStorageandloadFromLocalStorage函数,还需要删除loadFromLocalStoragefromcreateStore和整store.subscribe行代码。

行动

这里将存放我们的“函数”,我称它们为函数,但它们非常简单。函数会返回一个包含类型和有效载荷的对象,有效载荷就是我们用来指代传入参数的术语。

export const addItem = payload => {
  return {
    type: "LISTITEM_ADD",
    payload
  };
};
Enter fullscreen mode Exit fullscreen mode

使用提供商

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
);
Enter fullscreen mode Exit fullscreen mode

使用商店

我在文章开头就说过,有很多样板代码需要编写,现在我们终于完成了,终于可以开始使用这个商店了。

使用选择器

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);
Enter fullscreen mode Exit fullscreen mode

现在我们可以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));
Enter fullscreen mode Exit fullscreen mode

结语

一旦所有样板代码都已清除,跨组件访问数据就变得容易得多,我预见到它将在未来的项目中对我大有帮助。它还有一个额外的好处,那就是跨会话保存变得超级简单!

这周内容有点长,但我们总算完成了。感谢阅读。如果您有任何问题或更正,欢迎在下方留言。

再次感谢🦄🦄💕❤️🧡💛💚🤓🧠

文章来源:https://dev.to/link2twenty/react-redux-and-localstorage-2lih