【问题标题】:What is mapDispatchToProps?什么是 mapDispatchToProps?
【发布时间】:2017-07-23 05:49:02
【问题描述】:

我正在阅读 Redux 库的文档,其中包含以下示例:

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

这实际上没有任何意义。既然已经有mapStateToProps,为什么还需要mapDispatchToProps

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

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

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

【问题讨论】:

    标签: reactjs redux react-redux mapdispatchtoprops


    【解决方案1】:

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

    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)

    【讨论】:

    • 谢谢。我也想知道,首先dispatch是如何添加到道具中的?
    • 如果你不提供自己的mapDispatch 函数,Redux 将使用默认值。默认的mapDispatch 函数只接受dispatch 函数引用,并将其作为this.props.dispatch 提供给您。
    • dispatch方法由Provider Component传下来
    【解决方案2】:

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

    mapDispatchToProps 接收 dispatchprops,用于绑定动作创建者进行调度,以便在执行生成的函数时调度动作。

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

    React redux: connect: Arguments

    【讨论】:

    • 谢谢,但是dispatch 方法的价值是什么?它来自哪里?
    • 哦。调度基本上使动作启动 redux/flux 单向流。其他答案似乎比这更好地回答了您的问题。
    • 另外,dispatch方法来自&lt;Provider/&gt;本身提供的增强。它执行自己的高阶组件魔法,以确保调度在其子组件中可用。
    【解决方案3】:

    mapStateToPropsmapDispatchToPropsconnect 来自 react-redux 库提供了一种方便的方式来访问您的商店的 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 functionsHigher-Order Components

    【讨论】:

    • 所以 dispatch 基本上就像事件?
    • 它可能与事件有关,dispatch 只是一个函数,也是改变应用程序状态的唯一方法. mapStateToProps 是将 storedispatch 函数暴露给 React 组件的一种方式。另请注意,connect 不是 redux 的一部分,实际上它只是一个名为 react-redux 的实用程序和样板化缩减库,用于处理 react 和 redux。如果您将 store 从根 react 组件传递给子组件,则无需 react-redux 即可获得相同的结果。
    【解决方案4】:

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

    这真的只能在container-component 模式的上下文中回答,我发现首先阅读:Container Components 然后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 获取它显示的信息(通过 mapStateToProps 来自 redux 存储),它还从它的 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 等等。

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

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

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

    (注意:您不能将mapStateToProps 用于与mapDispatchToProps 相同的目的,因为您无法在mapStateToProp 中访问dispatch。所以您不能使用@987654347 @ 给被包装的组件一个使用dispatch的方法。

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


    1 请注意,我故意将容器明确命名为FancyButtonContainer,以强调它是一个“事物”——作为“事物”的容器的身份(因此存在!)有时会丢失简而言之

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

    大多数示例中显示的语法

    【讨论】:

    • 我还是想知道:在组件内直接调用 store.dispatch 无法处理所需功能怎么办?
    • @user2130130 无。这是关于好的设计。如果你将你的组件耦合到 store.dispatch,那么当你决定将 redux 分解,或者想在某个不基于 redxu 的地方使用它(或者我现在想不到的其他东西)时,你就会陷入困境很多变化。您的问题概括为“为什么我们要为'良好的设计实践'而烦恼-无论您如何编码,您都可以获得相同的功能”。提供了 mapDispatchToProps,因此您可以编写设计良好、清晰解耦的组件。
    • 我真正不明白的是:ALERT_ACTION 是动作函数还是从动作函数返回的type? :/ 好困惑
    • @JamieHutber 严格来说,ALERT_ACTION 与这个问题无关。它是 dispatch 的一个有效参数,而且碰巧在我的代码中,它来自一个“action builder”,它返回一个 dispatch 使用的对象,如 redux.js.org/docs/api/Store.html#dispatch 所述。这里的重点是如何调用dispatch在容器中描述并传入components props。该组件仅从其 props 中获取功能,其他任何地方都没有。在这种模式中“错误”的做法是将调度传递给组件并在组件中进行相同的调用。
    • 如果您有多个动作创建者需要作为道具传递给子组件,一种替代方法是在 mapDispatchToProps 中使用 bindActionCreators 包装它们(请参阅redux.js.org/docs/api/bindActionCreators.html);另一种选择是简单地为connect()提供一个action creators对象,例如connect(mapStateToProps, {actioncreators}),react-redux会用dispatch()为你包装它们。
    【解决方案5】:

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

    【讨论】:

      【解决方案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 动作映射到道具(我们组件的道具)

      所以 prop onTodoClickmapDispatchToProps 函数的一个键,它代表进一步调度动作 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())
            }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2018-04-14
        • 2016-06-15
        • 2016-09-16
        • 2018-01-03
        • 2018-06-15
        • 1970-01-01
        • 2018-05-10
        • 2017-05-03
        相关资源
        最近更新 更多