大多数时候,当我们获取数据时,我们是从作为服务器的外部端点 (API) 进行的。获取该数据后,我们对其执行 CRUD(创建、读取、更新、删除)操作。

本文将演示如何在 React & Redux 应用程序中正确地从 JSON 文件中获取数据并在前端使用它,同时解释 React-Redux 的工作流程。

我们将创建一个徽章来奖励获得超过 5 票的用户。我们将在本地模拟 JSON 数据,并为每个拥有超过five-votes的用户提供一个徽章,使用 react 和 redux 来消费数据。

在继续之前,我假设您具有React、React-Redux和JSON的基本知识。

设置本地 JSON 文件

在一个空白的 Create React App 项目中,在公共目录中创建一个名为data.json的本地 JSON 文件。

从 React 组件进行的 Fetch API 调用始终在此公共目录中查找文件或任何其他相关资产。Create-React-App在编译期间不会自动将您的资产放入此目录中,因此您必须手动执行此操作。

接下来,将一些虚拟 JSON 数据放入此文件中。出于演示目的,以下示例中使用的 JSON 数据是从 JSON Generator 生成的。如果您使用自己的 JSON,请确保其格式正确。

[
  {
    "id": 1,
    "name": "Daniel",
    "email": "[email protected]",
    "post": "I love football",
    "votes": 5
  }
]

**设置 React-Redux **

我们需要安装一些依赖项,我们将在整个项目中使用它们。

要安装它,请在终端中打开您的项目目录并编写以下代码:

npm i -s react-redux redux axios redux-thunk
or 
yarn add react-redux redux axios

此外,我们将安装fontaweasome,我们将在其中导入图标作为徽章。

npm i --save @fortawesome/fontawesome-svg-core
npm install --save @fortawesome/free-solid-svg-icons
npm install --save @fortawesome/react-fontawesome

或者

yarn add @fortawesome/fontawesome-svg-core
yarn add @fortawesome/free-solid-svg-icons
yarn add @fortawesome/react-fontawesome

在 src/ 目录中,让我们制作 6 个文件

  1. src/

  2. 常量.js

  3. action.js

  4. reducer.js

  5. store.js

  6. fontAwesome.js

src/constants.js

在 constant.js 中,我们需要添加一个获取用户的状态:

const USER = {
  LOAD: "REQUEST_USERS_DATA",
  LOAD_SUCCESS: "RECEIVE_USERS_DATA",
};

export default USER;

src/reducer.js

我们将在 reducer 中导入常量。 reducer 是一个纯函数,它采取一个动作和应用程序的初始状态并返回新状态。

action 描述了发生了什么,reducer 的工作是根据该 action 返回到新状态。

import USER from "./constants";

const initalState = {
  usersData: [],
  isLoading: false,
  isError: false,
};

const reducer = (state = initalState, action) => {
  switch (action.type) {
    case USER.LOAD:
      return {
        ...state,
        isLoading: true,
        isError: false,
      };
    case USER.LOAD_SUCCESS:
      return {
        ...state,
        usersData: action.usersData,
        isLoading: false,
      };
    default:
      return state;
  }
};

export default reducer;

src/action.js

此操作文件携带来自您的应用程序的信息负载以进行存储。

Redux 依赖于由 reducer 分发和监听的 action,reducers 会相应地更新状态。

import axios from "axios";
import USER from "./constants";

export const requestUsers = (data) => async (dispatch) => {
  dispatch({
    type: USER.LOAD,
  });
  try {
    const json = await axios.get("data.json");
    console.log(json);
    dispatch({
      type: USER.LOAD_SUCCESS,
      usersData: json.data,
      isError: false,
    });
  } catch (e) {
    dispatch({
      type: USER.LOAD_SUCCESS,
      usersData: [],
      isError: true,
    });
  }
};

src/index.js

在索引文件中,我们将导入fontawesome,以便任何组件都可以从它继承。

我们还需要提供者和商店。 Provider 组件使 Redux 存储可供任何需要访问 Redux 存储的嵌套组件使用。

Redux 存储是全局状态,用于存储您想要跨多个组件使用的数据,而无需在组件树的每个级别上钻取 props。 Redux 存储对存储的数据量没有限制,因此您几乎可以使用它来存储几乎任何东西,包括庞大的 JSON 数据。

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { store } from "./store";
import { Provider } from "react-redux";
import "./fontAwesome";

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);

src/fontAwesome.js

import { library } from "@fortawesome/fontawesome-svg-core";

import {
  faGithubAlt,
  faGoogle,
  faFacebook,
  faTwitter,
  faJediOrder,
} from "@fortawesome/free-brands-svg-icons";

library.add(faGithubAlt, faGoogle, faFacebook, faTwitter, faJediOrder);

src/store.js

一个 store 保存着应用程序的整个状态树。

改变内部状态的唯一方法是对它发送一个动作。然后 store 将从 reducer 接收到的新状态传递给组件。

import thunkMiddleware from "redux-thunk";
import { createStore, applyMiddleware } from "redux";
import reducer from "./reducer";

export const store = createStore(reducer, applyMiddleware(thunkMiddleware));

src/data.js

[
  {
    "id": 1,
    "name": "Daniel",
    "email": "[email protected]",
    "post": "I love football",
    "votes": 5
  }
]

src/App.js

我们从 react-redux 导入以下钩子:useSelectoruseDispatch

useSelector是一个函数,它将当前状态作为参数并返回您想要的任何数据,它允许您将返回值存储在函数组件范围内的变量中,而不是将它们作为道具传递下来。

useDispatch等价于mapDispatchToProps。我们将调用useDispatch并将其存储到变量 dispatch。这个钩子从 Redux 存储中返回对 dispatch 函数的引用。

您可以根据需要使用它来调度操作。我们通过调用 dispatch 并传入动作创建者的返回值来调度它。


import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import { requestUsers } from "./action";
import data from "./data.json";
import "./App.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
const App = () => {
  const { usersData, isLoading } = useSelector((state) => state);
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(requestUsers(data));
  }, []);

  return (
    <>
      {isLoading && <div className="loading">Data loading...</div>}
      {usersData.map((user) => {
        return (
          <div key={user.id} className="container">
            <div className="content">
              <h1>{user.name}</h1>
              <span>{user.email}</span>
              <h3>{user.post}</h3>
              Votes: {user.votes}
              {user.votes >= 5 ? (
                <div>
                  <FontAwesomeIcon icon={["fab", "jedi-order"]} size="3x" />
                </div>
              ) : (
                <p>Get up to five votes to have a badge</p>
              )}
            </div>
          </div>
        );
      })}
    </>
  );
};

export default App;

React-Redux 工作流程总结

![](data:image/svg+xml,%3csvg%20xmlns=%27http://www.w3.org/2000/svg%27%20version=%271.1%27%20width=%27543%27%20height=%27159%27/%3e)redux 数据流程图

<img altu003d"redux 数据流程图" srcsetu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FmyobtPSoKbQcY9jJlWQFuYiQqC42-4y9ac35jy.jpeg&wu003d640&qu003d75 1x, /_next/ image?urlu003dhttps%3A%2F%2Fcdn.hackernoon.com%2Fimages%2FmyobtPSoKbQcY9jJlWQFuYiQqC42-4y9ac35jy.jpeg&wu003d1200&qu003d75 2x" srcu003d"/_next/image?urlu003dhttps%3A%2F%2Fcdn.hackernoon. com%2Fimages%2FmyobtPSoKbQcY9jJlWQFuYiQqC42-4y9ac35jy.jpeg&wu003d1200&qu003d75" 解码u003d"async" data-nimgu003d"intrinsic" styleu003d"position:absolute;top:0;left:0;bottom:0;right:0;box -sizing:border-box;padding:0;border:none;margin:auto;display:block;width:0;height:0;min-width:100%;max-width:100%;min-height:100 %;max-height:100%;object-fit:contain" classu003d"image" loadingu003d"lazy">

redux 数据流程图

Redux 是 javascript 的可预测状态容器。

所以在一个 redux 数据流中,我们有一个 javascript 应用程序,它是应用程序的状态在 redux 存储中维护,但是,应用程序不能直接更新状态,它使用一个动作或调度一个动作来维护状态。一旦动作被调度,reducer 就会处理动作并更新当前存储。

Redux 在单页应用程序 (SPA) 中非常有用,因为它产生了单一的事实来源。 Redux 有一个 store,store 是一个包含整个应用程序状态的对象。不同的状态片段存储在对象树中。

要阅读有关 React-Redux 的更多信息,您可以阅读此文档。

编码愉快!

Logo

React社区为您提供最前沿的新闻资讯和知识内容

更多推荐