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

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

这实际上毫无意义。为什么你需要mapDispatchToProps当你已经有mapStateToProps?

它们还提供了以下方便的代码示例:

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

这个函数是什么?为什么它有用?


当前回答

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

mapDispatchToProps接收分派和道具,用于将动作创建者绑定到分派,以便在执行结果函数时分派动作。

我发现这只会让你不必在你的组件中做dispatch(actionCreator()),从而使它更容易阅读。

React redux: connect:参数

其他回答

我觉得没有一个答案能明确说明为什么mapDispatchToProps是有用的。

这个问题只能在容器组件模式的上下文中回答,我发现最好的理解方式是先阅读《容器组件然后使用React》。

简而言之,你的组件应该只关心显示内容。他们唯一能得到信息的地方就是他们的道具。

与“显示内容”(组件)分开的是:

你如何把东西展示出来, 以及你如何处理事件。

这就是容器的作用。

因此,模式中“设计良好”的组件看起来是这样的:

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

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

看看这个组件如何从props(通过mapStateToProps来自redux存储)中获得它所显示的信息,它还从它的props中获得它的动作函数:sendTheAlert()。

这就是mapDispatchToProps的用武之地:在相应的容器中

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

我想知道你是否能看到,现在它是容器1,它知道redux,调度,存储,状态和…的东西。

该模式中的组件FancyAlerter,它进行渲染,不需要知道任何这些东西:它通过它的props在按钮的onClick处调用它的方法。

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

所有这些看起来都很像文档中的todo示例,这里还有另一个答案,但我试图把它放在模式的光照下,以强调原因。

(注意:你不能将mapStateToProps用于与mapDispatchToProps相同的目的,其基本原因是你不能访问mapStateToProp内部的调度。因此,您不能使用mapStateToProps为包装组件提供使用分派的方法。

我不知道为什么他们选择把它分成两个映射函数-它可能会更整洁的mapToProps(状态,调度,道具)IE一个函数来做这两件事!


1注意,我故意显式地将容器命名为FancyButtonContainer,以突出它是一个“东西”——容器作为“东西”的身份(因此存在!)有时会在简写中丢失

导出默认连接(…) ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀

大多数示例中显示的语法

现在假设有一个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(),将调度动作映射到道具(我们组件的道具)

所以prop onTodoClick是mapDispatchToProps函数的一个键,它进一步委托调度addTodo动作。

此外,如果你想精简代码,绕过手动实现,那么你可以这样做,

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())
      }
    }
}

mapStateToProps, mapDispatchToProps and connect from react-redux library provides a convenient way to access your state and dispatch function of your store. So basically connect is a higher order component, you can also think as a wrapper if this make sense for you. So every time your state is changed mapStateToProps will be called with your new state and subsequently as you props update component will run render function to render your component in browser. mapDispatchToProps also stores key-values on the props of your component, usually they take a form of a function. In such way you can trigger state change from your component onClick, onChange events.

从文档:

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的无状态函数和高阶组件

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

mapDispatchToProps接收分派和道具,用于将动作创建者绑定到分派,以便在执行结果函数时分派动作。

我发现这只会让你不必在你的组件中做dispatch(actionCreator()),从而使它更容易阅读。

React redux: connect:参数

它基本上是一种速记。所以不用写:

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

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

this.props.onTodoClick(id);

或者在这种情况下,你会把它作为事件处理程序:

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

这里有一段丹·阿布拉莫夫的视频: Redux:使用connect()生成容器