ChatGPT解决这个技术问题 Extra ChatGPT

什么是 mapDispatchToProps?

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

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

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

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

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

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


S
Sridhar

我觉得没有一个答案明确说明为什么 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,它不需要知道任何这些东西:它通过它的 props 获取在按钮的 onClick 处调用的方法。

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

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

(注意:您不能将 mapStateToProps 用于与 mapDispatchToProps 相同的目的,因为您无权访问 mapStateToProp 中的 dispatch。所以您不能使用 mapStateToProps 来提供被包装的组件是一个使用 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() 包装它们。
S
Sabito 錆兎 stands with Ukraine

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

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)


谢谢你。我也想知道,首先如何将调度添加到道具中?
如果您不提供自己的 mapDispatch 函数,Redux 将使用默认值。该默认 mapDispatch 函数仅采用 dispatch 函数引用,并将其作为 this.props.dispatch 提供给您。
调度方法由 Provider Component 传递
C
Code Whisperer

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


M
Mayank Pandeyz

react-redux 库中的 mapStateToPropsmapDispatchToPropsconnect 提供了一种方便的方式来访问您商店的 statedispatch 功能。所以基本上 connect 是一个高阶组件,如果这对您有意义,您也可以将其视为包装器。因此,每次您的 state 更改时,都会使用您的新 state 调用 mapStateToProps,随后当您 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


所以调度基本上就像事件?
它可能与事件有关,调度只是一个函数,也是改变应用程序状态的唯一方法。 mapStateToProps 是将商店的调度功能公开给 React 组件的一种方法。另请注意,connect 不是 redux 的一部分,实际上它只是一个名为 react-redux 的实用程序和样板 reduce 库,用于与 react 和 redux 一起使用。如果将 store 从根 react 组件传递给子组件,则无需 react-redux 即可获得相同的结果。
M
Meet Zaveri

现在假设 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

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

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

S
Sabito 錆兎 stands with Ukraine

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

mapDispatchToProps 接收 dispatchprops,用于将动作创建者绑定到调度,以便在执行结果函数时调度动作。

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

React redux: connect: Arguments


谢谢,但是 dispatch 方法的价值是什么?它从何而来?
哦。调度基本上使动作启动 redux/flux 单向流。其他答案似乎比这更好地回答了您的问题。
此外,调度方法来自 <Provider/> 本身提供的增强功能。它执行自己的高阶组件魔法,以确保调度在其子组件中可用。