什么是 mapDispatchToProps?

What is mapDispatchToProps?

我正在阅读 Redux 库的文档,它有这个例子:

In addition to reading the state, container components can dispatch actions. In a similar fashion, you can define a function called mapDispatchToProps() that receives the dispatch() method and returns callback props that you want to inject into the presentational component.

这实际上是没有意义的。为什么你已经有了 mapStateToProps 还需要 mapDispatchToProps

他们还提供了这个方便的代码示例:

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

这个功能是什么,为什么有用?

基本上是shorthand。所以不必写:

this.props.dispatch(toggleTodo(id));

您将使用示例代码中所示的 mapDispatchToProps,然后在其他地方写入:

this.props.onTodoClick(id);

或者更可能在这种情况下,您将其作为事件处理程序:

<MyComponent onClick={this.props.onTodoClick} />

这里有一段 Dan Abramov 制作的有用视频: Redux: Generating Containers with connect() from React Redux (VisibleTodoList)

mapStateToProps 接收 stateprops 并允许您从状态中提取道具以传递给组件。

mapDispatchToProps 接收 dispatchprops 并用于绑定动作创建者以进行调度,因此当您执行结果函数时,动作将被调度。

我发现这只会使您不必在组件中执行 dispatch(actionCreator()),从而使其更易于阅读。

React redux: connect: Arguments

来自 react-redux 库的

mapStateToPropsmapDispatchToPropsconnect 提供了一种方便的方式来访问您的 statedispatch 函数店铺。所以基本上 connect 是一个高阶组件,如果这对您有意义,您也可以将其视为包装器。因此,每次您的 state 更改时, mapStateToProps 将与您的新 state 一起调用,随后当您 props 更新组件时,将 运行 渲染函数来渲染您的组件在浏览器中。 mapDispatchToProps 还在组件的 props 上存储键值,通常它们采用函数的形式。通过这种方式,您可以从组件 onClickonChange 事件中触发 state 更改。

来自文档:

const TodoListComponent = ({ todos, onTodoClick }) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
        onClick={() => onTodoClick(todo.id)}
      />
    )}
  </ul>
)

const mapStateToProps = (state) => {
  return {
    todos: getVisibleTodos(state.todos, state.visibilityFilter)
  }
}

const mapDispatchToProps = (dispatch) => {
  return {
    onTodoClick: (id) => {
      dispatch(toggleTodo(id))
    }
  }
}

function toggleTodo(index) {
  return { type: TOGGLE_TODO, index }
}

const TodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList) 

还要确保您熟悉 React stateless functions and Higher-Order Components

我觉得 none 的答案已经明确了为什么 mapDispatchToProps 有用。

这真的只能在 container-component 模式的上下文中回答,我发现通过第一次阅读可以最好地理解它:Container Components then Usage with React.

简而言之,您的 components 应该只关心显示内容。 他们唯一应该从中获取信息的地方是他们的道具

与"displaying stuff"(组件)的分离是:

  • 如何让内容显示,
  • 以及你如何处理事件。

这就是 containers 的目的。

因此,模式中的 "well designed" component 看起来像这样:

class FancyAlerter extends Component {
    sendAlert = () => {
        this.props.sendTheAlert()
    }

    render() {
        <div>
          <h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>
          <Button onClick={sendAlert}/>
        </div>
     }
}

查看此组件如何从道具(通过 mapStateToProps 来自 redux 商店)获取它显示的信息,它还从其道具获取其动作功能:sendTheAlert().

这就是 mapDispatchToProps 出现的地方:在相应的 container

// FancyButtonContainer.js

function mapDispatchToProps(dispatch) {
    return({
        sendTheAlert: () => {dispatch(ALERT_ACTION)}
    })
}

function mapStateToProps(state) {
    return({fancyInfo: "Fancy this:" + state.currentFunnyString})
}

export const FancyButtonContainer = connect(
    mapStateToProps, mapDispatchToProps)(
    FancyAlerter
)

我想知道你是否可以看到,现在是 container 1 知道 redux 和 dispatch 和 store 和 state 以及......东西。

模式中的 componentFancyAlerter,渲染不需要知道任何这些东西:它在 onClick 获取调用方法按钮,通过它的道具。

而且... mapDispatchToProps 是 redux 提供的有用方法,让容器可以轻松地将函数传递到其 props 上的包装组件中。

所有这些看起来很像文档中的待办事项示例,以及此处的另一个答案,但我已尝试根据模式对其进行投射以强调 为什么

(注意:您不能将 mapStateToProps 用于与 mapDispatchToProps 相同的目的,其基本原因是您无权访问 [=29= 内的 dispatch ]。所以你不能使用 mapStateToProps 给包装组件一个使用 dispatch 的方法。

我不知道他们为什么选择将其分解为两个映射函数 - 让 mapToProps(state, dispatch, props) IE 一个函数同时执行这两个函数可能更整洁!


1 请注意,我故意明确地将容器命名为 FancyButtonContainer,以强调它是一个 "thing" - 身份(因此存在!) "a thing" 的容器有时会在 shorthand

中丢失

export default connect(...) ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

大多数示例中显示的语法

mapStateToProps() 是一个实用程序,可以帮助您的组件更新状态(由其他一些组件更新),
mapDispatchToProps() 是一个实用程序,可帮助您的组件触发操作事件(调度可能导致应用程序状态更改的操作)

现在假设 redux 有一个动作:

export function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

导入后,

import {addTodo} from './actions';

class Greeting extends React.Component {

    handleOnClick = () => {
        this.props.onTodoClick(); // This prop acts as key to callback prop for mapDispatchToProps
    }

    render() {
        return <button onClick={this.handleOnClick}>Hello Redux</button>;
    }
}

const mapDispatchToProps = dispatch => {
    return {
      onTodoClick: () => { // handles onTodoClick prop's call here
        dispatch(addTodo())
      }
    }
}

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

正如函数名称所说 mapDispatchToProps(),将 dispatch 动作映射到 props(我们组件的 props)

所以 prop onTodoClickmapDispatchToProps 函数的关键,它委托进一步调度操作 addTodo

此外,如果您想 trim 代码并绕过手动实施,那么您可以这样做,

import {addTodo} from './actions';
class Greeting extends React.Component {

    handleOnClick = () => {
        this.props.addTodo();
    }

    render() {
        return <button onClick={this.handleOnClick}>Hello Redux</button>;
    }
}

export default connect(
    null,
    {addTodo}
)(Greeting);

确切的意思是

const mapDispatchToProps = dispatch => {
    return {
      addTodo: () => { 
        dispatch(addTodo())
      }
    }
}