与ReduxReact组件通信

Components are quite popular when designing applications. Because you can reuse them over and over again in your entire application. That is quite a time-saving feature for you. Of course, you can use all components in one javascript file and handle them. However, that causes lots of complexity. You can not read your code easily and maintain it whenever you need it. Can you imagine how difficult it would be to change a line of code out of 1000 lines and expect this code only affects where you intervene?

在设计应用程序时,组件非常流行。 因为您可以在整个应用程序中反复使用它们。 这对您来说是一个非常节省时间的功能。 当然,您可以在一个JavaScript文件中使用所有组件并进行处理。 但是,这导致很多复杂性。 您无法轻松阅读代码并在需要时对其进行维护。 您能想象在1000行中更改一行代码并期望该代码仅影响您干预的地方有多困难吗?

Image for post
Image-2.Components
图2组件

Let’s talk about Image-2. There are three components on the page. Let’s assume we don’t use components and code everything on one javascript file. We will have complex hundreds of lines of codes. For example, showing character detail is not related to the search bar or list items do not affect showing detail. As a matter of fact, main function of the red section(search bar) is searching for something. On the other hand, main function of the blue section(list) is to list items. You don’t need to use them in one place. These two components can split and communicate with each other. At this point, Redux will help us a lot. You will see how to use Redux in the rest of this article.

让我们谈谈Image-2。 页面上有三个组件。 假设我们不使用组件,而是在一个JavaScript文件中编写所有代码。 我们将有数百行代码。 例如,显示字符的详细信息与搜索栏无关,或者列表项不影响显示的详细信息。 实际上,红色部分(搜索栏)的主要功能是搜索内容。 另一方面,蓝色部分(列表)的主要功能是列出项目。 您无需在一个地方使用它们。 这两个组件可以拆分并相互通信。 在这一点上,Redux将为我们提供很大帮助。 您将在本文的其余部分中看到如何使用Redux。

目标是什么? (What is the goal?)

The main goal is an orginezed, legible code which should not be hundreds oflines in one javascript file.While you communicate components, you shouldn’t drown in the props chain. Main purpose here is to find your code easily whenever you want to change a line of your code.

主要目标是编写清晰易懂的代码,在一个javascript文件中不应包含数百行代码。在交流组件时,您不应陷入道具链中。 这里的主要目的是在您想更改代码行时轻松找到您的代码。

前提条件 (Pre-requirements)

The project is run on node.In case you do not have the node, you may download from the link below:

该项目在节点上运行。如果没有该节点,可以从以下链接下载:

Since the catche system of yarn is quite satisfactory, I use yarn instead of npm. Because I love the cache system of yarn. It is so easy to install it.

由于纱线的捕集系统相当令人满意,因此我使用纱线代替npm。 因为我喜欢纱线的缓存系统。 安装非常容易。

npm install -g yarn

As a last step, create the app.

最后一步,创建应用程序。

yarn create react-app ricky-and-morty

依存关系 (Dependencies)

Welcome to the new coding world.Now,we do not have to code everything by ourselves anymore.Projects have short due times. That’s why, we need to use these packages like API calls, handle dates, component communication, etc. It gives you lots of time to save. The packages which are used in this project are introduced in the following lines. Installation command line for this packages is given below:

欢迎来到新的编码世界。现在,我们不再需要自己编写所有代码。项目的到期时间很短。 因此,我们需要使用这些程序包,例如API调用,处理日期,组件通信等。它为您节省了大量时间。 以下各行介绍了此项目中使用的软件包。 该软件包的安装命令行如下:

yarn add axios redux react-redux redux-thunk

Axios

Axios

Axios is a Javascript library used to make HTTP requests from node.js or XMLHttpRequests from the browser and it supports the Promise API. It has lots of features like transforming JSON automatically, interception of requests and responses etc.

Axios是一个Javascript库,用于从node.js发出HTTP请求或从浏览器发出XMLHttpRequest,它支持Promise API。 它具有许多功能,例如自动转换JSON,拦截请求和响应等。

Redux

Redux

Redux is a predictable state container for JavaScript applications and a polyvalent tool for organizing the application states. You can use Redux whole JS Frameworks and vanilla JS. There are four main concepts of Redux: Action Creator, Action, Reducer, and State.

Redux是JavaScript应用程序的可预测状态容器,也是用于组织应用程序状态的多价工具。 您可以使用Redux整个JS框架和香草JS。 Redux有四个主要概念:Action Creator,Action,Reducer和State。

Image for post
Image-3. Modern Redux Flow Diagram
图3。 现代Redux流程图

Action: Actions are plain JS object that payloads of information that send your data from the application to the store. Actions have the type and optional payload. The payload is not essential here.

动作 :动作是普通的JS对象,用于承载信息负载,这些信息将数据从应用程序发送到商店。 动作具有类型和可选的有效负载。 有效负载在这里不是必需的。

const action = {
  type: UNIQUE_TYPE, // Describes what change we want to make to our data
  payload: data
}

Action Creator: An action creator is a function that returns an action object. Action Creator sends action objects to reducers with the help of type (dispatch).

动作创建者 :动作创建者是一个返回动作对象的函数。 动作创建者借助类型(调度)将动作对象发送到减速器。

const listFilterAction = (filterValue) => {
  return {
    type: listFilter,
    payload: filterValue,
  };
};

Reducer: The reducer is a function that takes two arguments to represent previous data and action. After that, it returns a new state.

Reducer :Reducer是一个带有两个参数的函数,用于表示先前的数据和操作。 之后,它将返回新状态。

const listFilterReducer = (initialState = '', action) => {
  switch (action.type) {
    case 'LIST_FILTER':
      return action.payload;
    default:
      return initialState;
  }
};


export default listFilterReducer;

State: The central repository of all data from reducer.

状态 :来自reducer的所有数据的中央存储库。

React-redux

React-redux

React-Redux is the React binding for Redux. It lets your React components read data from the Redux store and dispatch actions to the store to update data. There are two main concepts of React-Redux: connect and Provider.

React-Redux是Redux的React绑定。 它使您的React组件可以从Redux存储中读取数据,并向存储分派操作以更新数据。 React-Redux有两个主要概念:connect和Provider。

Provider: Provider is a tag by React-Redux. It makes the Redux store available to the rest of our application. That’s why you need to wrap all the components from the top.

Provider :Provider是React-Redux的标签。 它使Redux存储可用于我们的其他应用程序。 这就是为什么您需要从顶部包装所有组件的原因。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './pages/App';
import './assets/styles/main.css';
import 'semantic-ui-css/semantic.min.css';


import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import reducers from './redux/reducers';
const store = createStore(reducers, applyMiddleware(thunk));
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
);

Connect: The connect() function connects a React component to a Redux store.

Connect :connect()函数将React组件连接到Redux存储。

import { login, logout } from './actionCreators'


const mapState = state => state.user
const mapDispatch = { login, logout }


// call connect to generate the wrapper function, and immediately call
// the wrapper function to generate the final wrapper component.


export default connect(
  mapState,
  mapDispatch
)(Login)

Redux-thunk

Redux-thunk

import { characterApi } from '../../apis';
const listAction = () => async (dispatch) => {
  const response = await characterApi();
  dispatch({
    type: 'APP_CONSTANT',
    payload: response.data, // data from api
  });
};


export default listAction;

Redux actions work synchronously and only return plain objects. Normally, I do not prefer using API calls into a javascript file. I want to reach the API call wherever I want. But we have a problem here. The data from API call in actioncannot received, since it does not return a plain javascript object. Let’s check Gist-6, it returns a function. due to async and await. They are recieved with ES6 so we need to use Babel which returns a function. That’s why we need to use redux-thunk with middleware. The middleware dispatches action again and makes a plain function after that.

Redux动作同步工作,并且仅返回普通对象。 通常,我不喜欢在JavaScript文件中使用API​​调用。 我想在任何地方到达API调用。 但是我们这里有一个问题。 无法收到来自动作中的API调用的数据,因为它没有返回普通的javascript对象。 让我们检查Gist-6,它返回一个函数。 由于异步和等待。 它们与ES6一起接收,因此我们需要使用Babel返回函数。 这就是为什么我们需要在中间件中使用redux-thunk。 中间件再次调度动作,然后执行简单的功能。

Image for post
Image-4. Middleware Diagram
图4。 中间件图

and lastly lets add some UI for better looking applications.

最后,让我们添加一些UI,以使应用程序外观更好。

yarn add semantic-ui-css semantic-ui-react

Project Structure

项目结构

Image for post
Image-5. Project Structure
图片5。 项目结构

Don’t worry we are so close to coding. For the starter, I want to introduce to the project structure. Before passing through the coding part, I would like to introduce project structure.The project has many folders like assets, components, pages, API, and redux. Project folder names need to be specific and they are developed by teams. You need to change someone else’s code. Neat and legible structure is a total lifesaviour. It prevents lots of mess. So lets coding :)

不用担心,我们是如此接近编码。 首先,我想介绍一下项目结构。 在通过编码部分之前,我想介绍一下项目结构,该项目有很多文件夹,例如资产,组件,页面,API和Redux。 项目文件夹名称需要特定,并且由团队开发。 您需要更改其他人的代码。 整洁而清晰的结构是全部的生命来源。 它可以防止很多混乱。 因此,让我们编码:)

(Code)

First of all, we need to set the Redux-Store for the application. As I mentioned before, the store needs to be top of all components. That’s why I set it first called the javascript file(index.js).

首先,我们需要为应用程序设置Redux-Store。 正如我之前提到的,商店必须位于所有组件的顶部。 这就是为什么我首先将其设置为javascript文件(index.js)的原因。

import React from 'react';
import ReactDOM from 'react-dom';
import App from './pages/App';
import './assets/styles/main.css';
import 'semantic-ui-css/semantic.min.css';


import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import reducers from './redux/reducers';
const store = createStore(reducers, applyMiddleware(thunk));
ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.querySelector('#root')
);

You can find lots of information in Gist-7. Now, I would like to explain what the createStore function does. The createStore allows us to create a Redux-Store and it takes two arguments(sometimes three but we don’t need it here)reducers and middleware. Reducers might be more than one. You can find much more information later in this article.After creating the Redux-Store, we need to pass it into the Provider tag like line eleven(11).

您可以在Gist-7中找到很多信息。 现在,我想解释一下createStore函数的作用。 createStore允许我们创建一个Redux-Store,它接受两个参数(有时是三个,但这里不需要),归约器和中间件。 减速器可能不止一个。 您可以在本文后面找到更多信息。创建Redux-Store之后,我们需要将其传递到Provider标记(如第十一行(11)行)。

You will see a lot of variables from ‘./constants’ URL. I like to use my magic strings in one file and use them all over the application. It prevents mistyping

您会从“ ./constants”URL中看到很多变量。 我喜欢在一个文件中使用魔术字符串,并在整个应用程序中使用它们。 防止误涂

Now, Redux-Store generated.Let’s create the actions. Actions allow us to access the store and get the needed state.

现在,Redux-Store生成了,让我们创建动作 。 动作使我们能够访问商店并获得所需的状态。

// Basic Action
import { listFilter, listRickyAndMorty } from '../constants';
import { characterApi } from '../../apis';


const listFilterAction = (filterValue) => {
  return {
    type: listFilter,
    payload: filterValue,
  };
};


// Async Action
const listAction = () => async (dispatch) => {
  const response = await characterApi();
  dispatch({
    type: listRickyAndMorty,
    payload: response.data.results,
  });
};


export {
  listAction,
  listFilterAction
};

There are two action types in Gist-8. listFilterAction is a basic action receives an argument and returns a plain object. On the other hand, listAction is not basic. It returns a function and dispatches it again. Normally redux doesn’t allow us to return a function. However, middleware is used with redux-thunk so we are okay :)

Gist-8有两种动作类型。 listFilterAction是一个基本操作,它接收一个参数并返回一个普通对象。 另一方面,listAction不是基本的。 它返回一个函数并再次调度它。 通常,redux不允许我们返回函数。 但是,中间件与redux-thunk一起使用,所以我们可以:)

Time to create reducers. Reducers are our functions to keep the logic and change the state. It receives two arguments, previous state, and action. After actions return the object, redux checks the type that matches with reducer and creates a new state. You can manipulate the payload that came from the action argument. It allows you to carry your logic from JSX file to reducer. It provides less code complexity in the JSX files. You just need to call the reducer and get the wanted new state that’s all :)

是时候制造减速器了 。 减速器是我们保持逻辑并更改状态的功能。 它接收两个参数,先前的状态和操作。 操作返回对象后,redux会检查与reducer匹配的类型并创建一个新状态。 您可以操纵来自action参数的有效负载。 它允许您将逻辑从JSX文件传输到reducer。 它在JSX文件中提供了较少的代码复杂性。 您只需要调用reducer并获得所需的新状态即可:)

After actions are trigger, redux checks whole reducers and try to find matched type. When redux finds it, it is not going to stop, no matter what redux keep looking for new matches.

触发动作后,redux检查整个reducer并尝试找到匹配的类型。 当redux找到它时,无论什么redux继续寻找新的比赛,它都不会停止。

import { selectedCharacter, listRickyAndMorty } from '../constants';
import { combineReducers } from 'redux';


const selectedCharacterReducer = (initialState = null, action) => {
  switch (action.type) {
    case selectedCharacter:
      return action.payload;
    default:
      return initialState;
  }
};
const listReducer = (initialState = [], action) => {
  switch (action.type) {
    case listRickyAndMorty:
      return action.payload;
    default:
      return initialState;
  }
};


export default combineReducers({
  selectedCharacterReducer,
  listReducer,
});

We are already familiar with lots of things in Gist-10. Here, you will have more information about combineReducer as I promised. In projects, developers need more information about components. One reducer is not enough. combineReducer allows us to use more than one reducer. You can get the reducer how you named in this function(combineReducer).

我们已经熟悉Gist-10中的许多内容。 正如我所承诺的,在这里,您将获得有关CombineReducer的更多信息。 在项目中,开发人员需要有关组件的更多信息。 一个减速器是不够的。 CombineReducer允许我们使用多个减速器。 您可以在该函数中获得减速器的命名方式(combineReducer)。

Time to bring all together in one JSX file.

是时候将所有内容汇总到一个JSX文件中了。

import React, { useState, useEffect } from "react";
import { Container, Header, Grid, Dimmer, Loader } from "semantic-ui-react";
import { SearchInput, SelectionList, CharacterDetail } from "../components";
import { connect } from "react-redux";
import {
  listAction,
  listFilterAction,
  selectedCharacterAction,
} from "../redux/actions";
const App = (props) => {
  const [search, setSearch] = useState("");
  const [list, setList] = useState([]);
  useEffect(() => {
    props.listAction();
  }, []);
  useEffect(() => {
    setList(
      props.list.filter(({ name }) => {
        return name.toLowerCase().includes(props.listFilter.toLowerCase());
      })
    );
  }, [props.listFilter, props.list]);


  // functions
  const searchHandler = (event) => {
    props.listFilterAction(search);
  };
  const searchbarChangeHandler = (event) => {
    setSearch(event.target.value);
  };
  const listItemSelectHandler = (selectedCharacter, event) => {
    props.selectedCharacterAction(selectedCharacter);
  };


  // Render
  return (
    <div className="main">
      <Container>
        <Dimmer active={props.list.length === 0}>
          <Loader size="huge" inverted />
        </Dimmer>
        <Header as="h1">Rick and Morty Characters</Header>
        <Grid columns="two">
          <Grid.Row>
            <Grid.Column width={6}>
              <SearchInput
                change={searchbarChangeHandler}
                value={search}
                click={searchHandler}
              />
              <div className="selectionList">
                <SelectionList items={list} click={listItemSelectHandler} />{" "}
                {list.length === 0 && "No matched character"}
              </div>
            </Grid.Column>
            <Grid.Column width={10}>
              <CharacterDetail />
            </Grid.Column>
          </Grid.Row>
        </Grid>
      </Container>
    </div>
  );
};


const mapStateToProps = (state) => {
  return { list: state.characterList, listFilter: state.characterListFilter };
};
const mapDispatchToProps = {
  listAction,
  listFilterAction,
  selectedCharacterAction,
};
export default connect(mapStateToProps, mapDispatchToProps)(App);

When you look at the Gist-11 you notice that is so long. However, it is the shortversion. Imagine now, you put all components communication and API calls. Seventy-four lines would be more than double. As I mentioned earlier you are not working alone. Other developers may work here too. He/She is going to add some codes here too, mess will growing. Redux offers and gives you a neat and understandable project. Why not using it :)

当您查看Gist-11时,您会注意到它很长。 但是,这是短期版本。 现在想象一下,您将所有组件通信和API调用都放入了。 七十四行是两倍多。 如前所述,您并非一个人工作。 其他开发人员也可以在这里工作。 他/她也将在此处添加一些代码,混乱情况将越来越严重。 Redux提供并为您提供了一个简洁易懂的项目。 为什么不使用它:)

In Gist-11, you can see how to connect function works. Connect takes two arguments here(It might be one to four too). mapStateToProps allows to you to use state from Redux-Store. It is kind of a door to open Redux-Store. mapDispatchToProps object allows you to dispatch your data and set a new state.

在Gist-11中,您可以看到如何连接功能。 Connect在这里接受两个参数(也可能是一到四个)。 mapStateToProps允许您使用Redux-Store中的状态。 开设Redux-Store就像一扇门。 mapDispatchToProps对象允许您调度数据并设置新状态。

结语 (Wrap Up)

Redux is a milestone for component communication. It helps you to manage state management all over your components. It is not only this, more neat, organizer code structure, and lots of more. For further more details, you can visit the Redux official website.

Redux是组件通信的里程碑。 它可以帮助您管理所有组件的状态管理。 不仅如此,它还更加简洁,组织者代码结构以及更多其他内容。 有关更多详细信息,您可以访问Redux官方网站。

You can use the code structure from the source code. It is going to help you most of your projects. If you want to check the source code, please visit :

您可以使用源代码中的代码结构。 它会为您的大多数项目提供帮助。 如果要检查源代码,请访问:

Thanks for reading :)

谢谢阅读 :)

翻译自: https://medium.com/neyasistechnology/react-component-communication-with-redux-cac438d6dd93

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值