409

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

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

这实际上没有任何意义。为什么mapDispatchToProps你已经拥有了mapStateToProps

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

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

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

4

6 回答 6

635

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

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

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

与“显示的东西”(组件)分开的是:

  • 你如何让这些东西显示出来,
  • 以及你如何处理事件。

这就是containers目的。

因此,模式中的“精心设计”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>
     }
}

看看这个组件如何从 props 中获取它显示的信息(来自 redux store via mapStateToProps),它还从它的 props: 中获取它的动作函数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 以及......的东西。

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

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

所有这些看起来都非常像文档中的 todo 示例,以及此处的另一个答案,但我试图根据模式对其进行投射以强调为什么

(注意:您不能将其用于与您无权访问inside的基本原因mapStateToProps相同的目的。因此,您不能使用为包装的组件提供使用. mapDispatchToPropsdispatchmapStateToPropmapStateToPropsdispatch

我不知道他们为什么选择把它分成两个映射函数——让mapToProps(state, dispatch, props) IE 一个函数同时做这两个函数可能会更整洁!


1 请注意,我特意明确命名了 container FancyButtonContainer,以强调它是一个“事物” - 容器作为“事物”的身份(以及因此存在!)有时会在速记中丢失

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

大多数示例中显示的语法

于 2016-10-16T08:00:55.563 回答
94

它基本上是一个简写。所以不必写:

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)

于 2016-09-09T20:47:07.583 回答
64

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

于 2017-03-03T06:32:30.087 回答
26

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

来自文档:

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

于 2016-09-10T07:43:07.820 回答
6

现在假设 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动作映射到道具(我们组件的道具)

所以 proponTodoClick是一个 key to mapDispatchToPropsfunction,它进一步委托 dispatch action 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())
      }
    }
}
于 2019-04-02T10:10:33.887 回答
4

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

mapDispatchToProps接收dispatchprops用于将动作创建者绑定到分派,因此当您执行结果函数时,动作会被分派。

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

React redux:连接:参数

于 2016-09-09T20:52:30.550 回答