上节课我们简单介绍了一下react-redux库,讲到了react-redux这个库把项目中的组件分为UI组件和容器组件,那么这节课我们就来介绍一下如何来连接UI组件和容器组件。

回顾

在开始这节课的学习之前,我们把上节课的内容来简单回顾一下

  • react-redux库把组件分为两类
  • UI组件
  • 容器组件
  • 只有容器组件可以直接操作redux
  • UI组件必须通过容器组件来操作redux
  • UI组件所需要的redux中的状态以及操作状态的方法都要由容器组件通过props来交互

以上便是上节课的主要内容,接下来我们开始这节课的学习。

UI组件改写

我们来想一下我们之前的案例中组件都在哪?是不是在components文件夹中?通常我们在编写react项目的时候,UI组件都会放在这里,而容器组件都放在container文件夹中,那么我们先来把我们的Sum组件改成一个UI组件吧。那么,既然是UI组件的话,我们的组件中是不是就不能有关于redux的任何东西的存在?

import React, { Component } from 'react'

export default class Sum extends Component {
  render() {
    return (
      <div>
        <h1>当前求和为:???</h1>
        <select ref={c => this.selectNum = c}>
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
        </select>
        <button onClick={this.add}>+</button>
        <button onClick={this.dec}>-</button>
        <button onClick={this.odd}>odd</button>
        <button onClick={this.async}>async</button>
      </div>
    )
  }
  add = () => {
    const { value } = this.selectNum;
  }
  dec = () => {
    const { value } = this.selectNum;
  }
  odd = () => {
    const { value } = this.selectNum;
  }
  async = () => {
    const { value } = this.selectNum;
  }
}

现在我们是不是把所有的redux相关的内容全部删掉了?但是现在我们的所有功能是不是都没法用了?因为我们到现在还没有去实现我们的容器组件,所以说我们目前还是不能去操作redux的。

创建容器组件

现在我们已经成功地把我们之前的组件改成一个UI组件了,那么大家说接下来要干什么?是不是要给我们的UI组件准备一个容器组件?只有有了容器组件我们才能跟redux来进行交互啊。那么我们来创建一个容器组件吧。但是我们的容器组件怎么写呢?直接定义一个类组件?那肯定不行的啊,我们说了这个容器组件是直接和redux打交道的组件,那么这里的组件不能靠我们自己写,我们就需要借助react-redux来生成这个组件。那么我们是不是要安装这个库?npm i react-redux,安装完这个库我们来创建这个组件吧。

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

export default connect()(SumUI);

这段代码是什么意思呢?我们来想一下,容器组件是干什么的?是不是用来使得UI组件可以间接性地使用和操作redux?这是不是相当于一个桥梁的作用?那么这座桥的两端是什么?是不是UI组件和redux?所以说我们先不管别的,最起码我们得先把我们这个桥的两端引入进来吧?所以第一行引入Sum组件。

那么第二行我们引入redux,我们之前在案例中是不是已经写好了我们的redux相关的东西,总共 4 个文件,那么我们怎么引入?我们用redux是不是一直都是store在居中调度?不管分发动作也好,还是存储state也好,我们是不是都是store在做这部分内容?我们有直接来调用reducer吗?是不是根本没有?那么这样的话,我们是不是只要引入store就可以了?

然后后桥梁的两端都有了,是不是要把桥搭起来?这个桥怎么搭?我们说要用react-redux来搭,我们react-redux中有一个函数叫connect,这个函数很好理解,桥梁是用来连接河两岸的嘛。所以说我们调用这个函数,而这个函数的返回值是一个函数,这个API设计的就是让我们柯里化调用,当我们柯里化调用了这个函数之后,我们就可以生成一个所谓的容器组件。但是这个容器组件是谁的容器组件呢?所以说我们要把我们的UI组件传给这个函数的返回函数。

但是我们现在先不把代码写完整,我们一步步来,我们先让容器组件和UI组件先建立联系。那么我们现在就还用不到store,那么我们生成了一个容器组件了,是不是要把这个容器组件暴露出去?所以最后我们export一下。

那么当我们创建了容器组件,而且容器组件里面还有UI组件来做子组件,那么我们是不是就要在页面上来渲染容器组件啊?不然的话我们就等于没有创建容器组件啊,一个组件你创建了不渲染,那还创建他干什么呢。所以我们修改一下App组件中的引入就可以了。那么我们来看一下效果吧:

image-20220119114627417

诶呦,报错了。这是为啥呢?报的什么错啊?说找不到store,为什么找不到?我们说了容器组件是干什么的?是不是连接UI组件和redux的一个桥梁?我们把UI组件交给了容器组件,但是我们实现连接store了吗?是不是没有?但是我们是不是引入了store了?但是为什么这里还会提醒我们说找不到store呢?

因为容器组件要得到的store不能由开发者手动去引入。所以我们把引入store那一步给删掉。但是可能有人说了,那么我们引入了都找不到,删掉不就更找不到了嘛。别急,我来问一下,这个store是哪个组件要用?是不是容器组件?容器组件有没有渲染?是不是在App组件中渲染了?我们从App组件中把store通过props传给容器组件才是正确的方式。那么我们来改一下吧:

import React, { Component } from 'react'
import Sum from './containers/Sum'
import store from './redux/store'

export default class App extends Component {
  render() {
    return (
      <div>
        <Sum store={store}/>
      </div>
    )
  }
}

我们在App组件中引入store,然后传给容器组件,来看一下效果:

image-20220119115659387

这次就正常展示了页面了。以上呢就成功将UI组件和容器组件成功连接起来了

总结

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

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/connect_ui_and_container/