Redux代码中发生了什么...混淆了mapDispatchToProps,调度和连接

时间:2018-10-12 20:32:44

标签: reactjs

我正在关注一个反应教程,我有几个问题。

我对该功能感到困惑:

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchWeather }, dispatch)
}

我想细分该功能的每个部分。

如何将动作创建者连接到容器? this.props.fetchWeather的工作代码如何?这是对此负责吗?:

function mapDispatchToProps(dispatch) {

如果是,这是怎么做的?

  return bindActionCreators({ fetchWeather }, dispatch)

那负责确保从动作创建者返回的动作对象向下流入中间件和化简器吗?

那是怎么回事:

function mapDispatchToProps(dispatch)

mapDispatchToProps只是约定俗成的还是它是React的一部分?

最后,此导出在做什么:

export default connect(null, mapDispatchToProps)(SearchBar);

连接在做什么?对我有什么作用?

Here is my whole code for reference:


import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { fetchWeather } from '../actions/index';

class SearchBar extends Component {
  constructor(props) {
    super(props);

    this.state = { term: '' };

    this.onInputChange = this.onInputChange.bind(this);
    this.onFormSubmit = this.onFormSubmit.bind(this);
  }

  onInputChange(event) {
    this.setState({ term: event.target.value });
  }

  onFormSubmit(event) {
    event.preventDefault();

    this.props.fetchWeather(this.state.term);
    this.setState({ term: '' });
  }

  render() {
    return (
      <form onSubmit={this.onFormSubmit} className="input-group">
        <input
          placeholder="Get a five-day forecast in your favorite cities"
          className="form-control"
          value={this.state.term}
          onChange={this.onInputChange}
        />

        <span className='input-group-btn'>
          <button type="submit" className="btn btn-secondary">
            Submit
          </button>
        </span>
      </form>
    );
  }
}

function mapDispatchToProps(dispatch) {
  return bindActionCreators({ fetchWeather }, dispatch)
}

export default connect(null, mapDispatchToProps)(SearchBar);

1 个答案:

答案 0 :(得分:2)

一个非常简洁的答案是:

  • mapStateToProps()是一个实用程序,可以帮助您的组件获取更新状态(由其他一些组件更新)
  • mapDispatchToProps()是一个实用程序,可以帮助您的组件触发操作事件(调度操作可能会导致应用程序状态更改)
  • bindActionCreators()通常用于要将某些动作创建者传递给不了解Redux 的组件,并且不想传递调度或Redux的情况。存储到它。
  • <Provider>使Redux存储可用于“连接的” React组件。
  • connect()是一个高阶组件(HOC),可让您将Redux状态注入常规的React组件中。

让我们深入一点

ReactJS- JS库,用于构建用户界面。
Redux- JS库,用于管理应用程序状态。

使用react-redux将它们放在一起:

如果我们想将我们的React应用程序与Redux商店链接,我们首先必须让我们的应用程序知道该商店存在。这是react-redux库的第一个主要部分,即Provider

Providerreact-redux库提供给我们的React组件。它仅用于一个目的:“为商店提供”其子组件。

提供商

使Redux存储可用于以下组件层次结构中的connect()调用。通常,如果不将父组件或祖先组件包装在connect()中,就无法使用<Provider>。因此,最终connect做到了这一点,它将您的React应用程序连接到Redux商店。

//This is the store we create with redux's createStore method
const store = createStore(todoApp, {})

// Provider is given the store as a prop
render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('app-node')
)

道具

  • 商店(R edux商店):应用程序中的单个Redux商店。
  • 孩子反应元素):组件层次结构的根。

Connect函数的解释和用法:

现在我们已经将redux存储“提供”到了我们的应用程序,现在我们可以将组件连接到它了。我们之前建立了没有办法直接与商店互动的方法。我们既可以通过获取其当前的state来检索数据,也可以通过调度一个动作来更改其状态(我们只能访问前面显示的redux流程图的顶部和底部)。这正是connect()的作用。

要使用connect(),您需要定义一个名为mapStateToProps的特殊函数,该函数描述如何将当前的Redux商店状态转换为您要传递给演示组件的道具包装。


除了读取状态之外,容器组件还可以调度动作。以类似的方式,您可以定义一个名为mapDispatchToProps()的函数,该函数接收dispatch()方法并返回要注入到演示组件中的回调道具。


简单的解释和mapStateToProps的基本示例

存储是一个框,其中包含整个应用程序状态。想象一下,这个盒子在一个未知的位置。

组件需要将一些东西直接拿出来,但它们只需要其中存储的一些东西。组件从盒子中知道了他们需要什么,但他们不知道盒子在哪里。

mapStateToProps函数是一个筛选器,用于选择组件中需要框内的哪些内容。选定的东西成为组件属性。

mapStateToProps函数还不够,因为它在框中选择了所需的内容,但不知道该框在哪里。

connect函数知道该框位于何处,并将其传递给mapStateToProps函数,以便它可以获取所需的内容。

结论: mapStateToProps 仅返回当前状态的指定部分。 mapStateToProps获取馈送到其组件的数据。

 const mapStateToProps = (state) => {
     return { things: state.things }
};

因此,现在我们可以将状态的该部分用作props -> this.props.things


但是如果组件想要更改状态怎么办?这就是mapDispatchToProps进入的地方。

简单的解释和mapDispatchToProps的基本示例

顾名思义,此函数通过将动作指向动作创建者来指导动作的发送或发送。例如:

const mapDispatchToProps = () => {
     return {
          addThing: addThing,
          doAnotherThing: doAnotherThing
     }
}

mapDispatchToProps在组件中使用dispatch函数,并在触发该函数时针对Redux reducer执行它们。请记住,道具不仅是对象,还可以是函数。这是mapDispatchtoProps适用的地方。 MapDispatchToProps允许您将状态更改分派到商店。一个示例是单击按钮,一旦安装了组件,该按钮便触发刷新或自动加载数据。

动作创建者可以作为道具提供给组件,通常与组件中包含的事件处理程序函数相关联:

handleOnClick() {
     this.props.addThing();
};

但是,返回动作创建者只是其中一部分。我们还希望将返回action的发送到商店。我们该怎么做?我们使用Redux的bindActionCreators()

bindActionCreators()的简单说明和基本实现:

将值是动作创建者的对象转换为具有相同键的对象,但每个动作创建者都包装在分派调用中,以便可以直接调用它们。

通常,您应该直接在Store实例上直接调用dispatch。如果您将Redux与React一起使用,则react-redux将为您提供调度功能,因此您也可以直接调用它。

bindActionCreators的唯一用例是,当您要将一些动作创建者传递给一个不了解Redux的组件,并且您不想将调度或Redux存储传递给它时。

要实现此目标,我们:

import { bindActionCreators } from 'redux';
...
const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
         addThing: addThing,
         doAnotherThing: doAnotherThing
         }, dispatch);
};

bindActionCreators()函数接受操作创建者和商店的调度函数作为参数,并返回一个dispatch函数,该函数使用action creator的返回值作为参数。

再一次,connect()函数将所有这些联系在一起,我们在其中传递mapDispatchToProps作为第二个参数。例如:

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);

这将导出一个既可以从商店中获取当前状态的组件,又可以向商店调度一个动作以触发并更新状态

现在,我们将其与一些TodoItem.js React功能组件结合起来:

import { connect } from 'react-redux'

const TodoItem = ({ todo, destroyTodo }) => {
  return (
    <div>
      {todo.text}
      <span onClick={destroyTodo}> x </span>
    </div>
  )
}

const mapStateToProps = state => {
  return {
    todo: state.todos[0]
  }
}

const mapDispatchToProps = dispatch => {
  return {
    destroyTodo: () =>
      dispatch({
        type: 'DESTROY_TODO'
      })
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoItem)

mapStateToPropsmapDispatchToProps都是纯函数,分别提供了状态“ state”和“ dispatch”。此外,这两个函数都必须返回一个对象,然后将其键作为它们所连接的组件的props传递。

在这种情况下,mapStateToProps返回一个只有一个键的对象:“ todo”,而mapDispatchToProps返回一个具有 destroyTodo 键的对象。< / p>

导出的连接组件为todo功能组件提供了destroyTodoTodoItem作为道具