什么是mapDispatchToProps?

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

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

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

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

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

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

280343 次浏览

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

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

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

this.props.onTodoClick(id);

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

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

这里有一个由Dan Abramov制作的视频: Redux:使用connect()生成容器 < / p >

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

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

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

React redux: connect: Arguments

react-redux库中的mapStateToPropsmapDispatchToPropsconnect提供了一种方便的方式来访问你的商店的statedispatch函数。基本上,connect是一个更高阶的组件,你也可以把它看作一个包装器,如果你觉得有意义的话。因此,每次你的state被更改时,mapStateToProps将与你的新state一起被调用,随后,当你props更新组件将运行渲染函数来在浏览器中渲染你的组件。mapDispatchToProps还在组件的props中存储键值,通常它们采用函数的形式。这样你就可以从你的组件mapDispatchToProps3, mapDispatchToProps4事件触发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无状态函数高阶组件

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

这实际上只能在container-component模式的上下文中回答,我发现最好的理解方式是第一次阅读:容器组件然后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、分派、存储、状态和……的东西。

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

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

所有这些看起来都很像文档中的todo示例,这里还有另一个答案,但我试图在模式的光下投射它,以强调为什么

(注意:你不能将mapStateToProps用于与mapDispatchToProps相同的目的,其基本原因是你不能在mapStateToProp中访问dispatch。所以你不能用mapStateToProps给被包装的组件一个使用dispatch的方法。

我不知道为什么他们选择把它分解成两个映射函数-它可能已经有mapToProps(state, dispatch, props) IE一个函数来做这两个更整洁!


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

< p > export default connect(...) ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀< / p >

大多数示例中显示的语法

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)

因此道具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())
}
}
}