上节课我们介绍了如何将容器组件和UI组件连接起来,这节课我们来介绍一下react-redux的基本使用。

回顾

在开始这节课的内容之前,我们对上节课的内容做一个简单的回顾

  • 容器组件是连接UI组件和redux的桥梁
  • 容器组件要接收到store,但是必须通过props传入,不可以手动引入
  • react-redux提供的connect高阶函数来创建容器组件

以上便是上节课的主要要点,接下来我们来进行这节课的学习。

验证容器组件与UI组件的父子关系

我们之前得代码中是不是已经引入了UI组件?而且是不是也已近创建了容器组件?其实store是不是也已经在了,只不过我们还没有进行连接,那么我们接下来是不是就要让这座桥正式生效来让UI组件和redux连接起来了呢?先不忙,我们先来验证一下UI组件和容器组件的关系。

那么容器组件和UI组件是什么关系?我们之前在分析原理图的时候,是不是就已经说过了,UI组件是容器组件的子组件。那么我们来验证一下他们之间的父子关系是不是真的。但是怎么验证呢?

image-20220119121446402

我们来打开控制台,然后切换到开发者工具中,这里是不是很明显就可以看出来这两个是父子关系?

UI组件展示

那么我们现在也验证了容器组件和UI组件的父子关系了。那么我们页上展示的数据从哪来?我们之前的案例中是不是直接从reduxstate里面读出来的?但是现在我们还没有连接redux,而且UI组件负责展示,而UI组件不允许直接去找redux要数据,那么是不是要通过容器组件?那么容器组件和UI组件之前的通信是不是直接使用props就行了?

那么我们怎么从容器组件给UI组件传东西啊?我们打开了容器组件的代码,我们看不到UI组件标签的影子啊,那这还传什么props啊,没学过啊。

那么我们来讲一下,我们创建容器组件是不是要调用connect?这个函数是高阶函数?我们要柯里化调用。当我们第一次调用connect函数的时候,要传入两个参数:

  • 这两个函数都是函数
  • 第一个参数函数的返回值作为状态通过props传给了UI组件
  • 第二个参数函数的返回值作为操作状态的方法通过props传给UI组件

那么我们来看一下:

import SumUI from '../../components/Sum';
import { connect } from 'react-redux';

const data = () => ({ a: 100 });
const method = () => ({ b: () => console.log(123) });

export default connect(data, method)(SumUI);

我们来看上面这段代码,什么意思?第一个函数我们是不是返回一个对象?这个函数是不是我们connect函数第一次调用的时候传递的第一个参数?那么这个函数返回的对象是不是就作为状态通过props传给了UI组件。为什么要返回一个对象啊?我们这里是不是通过props传的?那么通过props传的话,不是对象我们在UI组件通过什么key来取这个值呢?那么为什么说是作为状态呢?因为这个东西是存在redux中的状态。但是我们现在是不是还没有连接redux啊,所以说先手写一个出来。

那么第二个函数则是第二个参数,这个函数呢也返回一个对象,这个对象的key也就作为propskey,而value就是一个函数,这个函数是用来操作状态的方法。那么我们在UI组件中来打印一下收到的props吧:

image-20220119123921189

是不是我们传的东西都传进去了,而且,react-redux还自动传了个store。我们下不用管这些。那么我们现在是不是能通过这种方法来让我们的UI组件拿到初始值来做页面的展示了啊?那么我代码就不贴了,大家改一下就行了。

获取state

我们现在已经可以通过容器组件给UI组件传递数据和方法了,那么我们现在传给UI组件的数据是不是都是我们写死的?但是我们实际过程中能写死吗?是不是不能啊?那么我们就要从redux中取啊,怎么取?是不是调用getState就行了?那么是谁来调用呢?是不是store来调用getState方法?那么我们怎么办?

我们之前说了第一个参数函数的返回值作为状态传给UI组件,那么这个参数函数是谁调用的?是不是react-redux调用的?而这个函数的作用是什么?是不是就只把数据传进去啊?所以说这个函数在被调用的时候react-redux就已经自动把state的值传给函数了。所以说我们直接在这个函数接一下,就可以了,那么我们来看一下:

import SumUI from '../../components/Sum';
import { connect } from 'react-redux';

const data = state => ({ sum: state });
const method = () => ({ cons: () => console.log(123) });

export default connect(data, method)(SumUI);

我们这里稍微显得规范一点,把key给改了一下。那么这个时候我们的页面是不是就可以拿到我们的值了?那么页面上不就可以正常展示了嘛:

image-20220119125344553

我们来看一下,这次我们直接从redux中拿到了状态值展示到了页面上。那么这是不是意味着我们已经成功通过容器组件将UI组件和redux连接起来了?如果没有连接起来的话,我们还能在UI组件中拿到redux中的值吗?但是我们的UI组件中我们有调用任何跟redux有关的东西吗?有任何reduxAPI吗?是不是没有?

实现动作

那么我们继续往下看,我们是不是也给UI组件传了一个方法?我们传的方法是一个打印 123 的函数,那么我们在UI组件中来用一下试试能不能用。我们把+按钮的onClick事件的回调换成了this.props.cons,那么我们点击一下按钮来看一下效果:

image-20220119130100948

也成功打印了。那么我们是不是就意味着我们把我们所有的动作都通这个方法来实现就行了呢?

// Sum 容器组件
import SumUI from '../../components/Sum';
import { connect } from 'react-redux';
import { createIncrementAction } from '../../redux/sum_action_creator';

const data = state => ({ sum: state });
const method = dispatch => ({ increment: data => dispatch(createIncrementAction(data)) });

export default connect(data, method)(SumUI);
// Sum UI组件
export default class Sum extends Component {
  render() {
    return (
      <div>
        ...
        <button onClick={this.add}>+</button>
        ...
      </div>
    )
  }
  add = () => {
    const { value } = this.selectNum;
    this.props.increment(value * 1)
  }
  ...
}

我们来看一下代码,我们直接在我们的容器组件中把传给UI组件的方法改了一下,这个方法接收一个data,然后把这个data直接传给了我们的Action Creator,但是我们是不是要把行动对象分发下去才能干活啊?是不是就要用store.dispatch?那么这个store从哪来?我们第一个函数是专门传state的,所以第一个函数可以接到state,那么第二个函数是专门通过动作来操作状态的,状态要由store分发,那么这个函数是不是就可以接收到store?其实不是,react-redux给你封装得更加方便,这里他直接把dispatch传给你了。

然后再来到UI组件中,我们的+按钮的回调中是不是取了我们下拉框选得值,然后再把值传给传进来的这个函数那么是不是就可以实现我们的加法操作了呢?我们来看一下效果:

iShot2022-01-19 13.19.53

现在我们就可以实现我们的加操作,那么其他的几个操作是不是就简单了,我们这里就不再赘述了。

总结

以上就是这一小节关于react-redux的基本使用,但是上面的代码并不规范。

  • connect函数在第一次调用时要接收两个参数
  • connect函数第一次调用时接收到的参数必须都是函数
  • 第一个函数叫mapStateToProps,返回值必须是一个对象,对象的valueredux中存的状态值,作为状态通过props传给UI组件
  • 第二个函数叫mapDispatchToProps,返回值必须是对象,对象的value必须是函数,作为操作状态的方法,通过props传给UI组件

Copyright statement:The articles of this site are all original if there is no special explanation, indicate the source please when you reprint.

Link of this article:https://work.lynchow.com/article/use_react_redux_basic/