你有太多的问题,我们如何努力解释这里发生的事情可能会让你更加困惑。我强烈建议您观看 Redux 创建者的这两个视频:
Redux
和
惯用的 Redux入门
这些视频解释了什么是 Redux,它的各个部分是如何组合在一起的。因此,在学习任何其他教程之前,首先要掌握 Redux 本身。
此外,Redux 的官方文档也很棒,如果您将其与视频一起学习,对您的学习会很有帮助。
但是,无论如何,让我回答你的问题。
第一个问题
我不明白的部分是这样的:
connect(mapStateToProps, mapDispatchToProps)(BookList)
到底是怎么回事?这部分是否负责使组件 BookList 可以使用状态和调度方法?
回答
connect这里是由react-redux包提供的,而不是redux它本身。它是一个辅助高阶函数,用于向组件打开状态和动作创建器。所以,你猜对了。这就是人们通常将他们的组件连接到商店以获取状态和分派(以使用动作创建者)的方式。
第二个问题
function mapDispatchToProps(dispatch) {
// Whenver selectBook is called, the result should be passed to all of the reducers.
// selectBook value is an actionCreator, a function.
return bindActionCreators({ selectBook: selectBook }, dispatch)
}
这些是内置的 redux 函数吗?他们返回什么?到底是怎么回事?什么是派遣?
右边的值 selectBook 是一个函数吧?所以我猜它被调用了,返回值将通过 dispatch 方法流经 reducer?但是 bindActionCreators 在做什么呢?
如何在组件 BookList 中提供props?
回答
不,它们不是像我在第一个答案中解释的那样内置于 Redux 函数中。mapStateToProps将您的状态打开到您的组件并将其作为props提供。所以,如果你打开任何状态给你的组件,connect并且mapStateToProps你得到这个状态作为props。在您的示例中,您books从全局状态获取状态并将其打开books到您的组件。然后这个组件将其作为this.props.books.
mapDispatchToProps将您的动作创建者函数作为props打开给您的组件。有几种使用它的方法,bindActionCreators是其中之一,但实际上您在这里不需要它。如果您在将动作创建者分派或传递给不知道 Redux 的子组件时需要它,则可以获取状态。所以,bindActionCreators不是一个好的开始理解mapDispatchToProps。
基本上是这样的:
const mapDispatchToProps = dispatch => ({
someFunction: () => dispatch(someFunction())
})
在这里,您someFunction()以 name 的形式向您的组件打开您的动作创建者someFunction。你可以使用不同的名字,或者你可以在这里做其他员工,然后dispatch根据这个做你的动作创建者。但是在这个例子中,你没有做任何额外的事情,只是调度动作创建者。所以,有一个简写:
const mapDispatchToProps = {
someFunction,
}
是的,对于这种情况,这会做同样的事情。甚至,还有一个更短的:
connect(mapStateToProps, {someFunction})(Component)
不使用 amapDispatchToProps你可以像这样使用你的动作创建者,然后在你的组件中作为props。
此外(是的,还有更多 :))在连接中不使用任何函数参数的事件,我们可以使用动作创建者。
connect()(Component)
connect(mapStateToProps)(Component)
如果我们mapDispatchToProps像上面的方法之一一样跳过,dispatch则会自动传递给组件props。然后,我们可以像使用任何其他props一样使用它来调度我们的动作创建者:
this.props.dispatch(someFunction())
对于你的例子,它是这样的(我知道这个应用程序,所以我在这里使用真实的动作创建者示例)。
你可以这样写mapDispatchToProps:
const mapDispatchToProps = dispatch => ( {
selectBook: book => dispatch( selectBook( book ) ),
} );
在这里你在你的组件中使用selectBookasthis.props.selectBook并调度一个动作。你实际上看到你的props触发了一个函数,它在这里调度你的真实动作创建者。请记住,动作创建者返回对象,这些对象需要被分派才能通过 reducer。因此,您正在调度您的动作创建者(由selectBook.
现在,在bindActionCreators不使用其真正优势的情况下,您可以将其写为:
const mapDispatchToProps = dispatch => (
bindActionCreators( { selectBook: selectBook }, dispatch )
);
或者使用 ES6 的一些具有相同名称的对象键的简写:
const mapDispatchToProps = dispatch => (
bindActionCreators( { selectBook }, dispatch )
);
这比第一个略短。你不需要指向一个函数并调度它。您将动作创建者交给了bindActionCreators它,它会为您完成工作。
现在,由于您只是在调度,因此较短:
const mapDispatchToProps = {
selectBook,
};
即使没有mapDispatchToProps:
connect( mapStateToProps, { selectBook } )( BookList )
因此,Provider,connect正在提供,react-redux以使我们的生活更轻松。mapStateToProps和mapDispatchToProps是connect等待的功能。名称并不重要,我们可以为它们使用任何名称,但这些是每个人都使用的事实上的名称。顺序很重要,如果我们想跳过,mapStateToProps我们必须null在它的位置使用,例如:
connect( null, mapDispatchToProps )( Component )
如果没有connect其实我们可以使用store和它包含什么getState,dispatch,subscribe用两种方法的任何组件:
- 不要一直使用as props
react-redux并将其传递store给您要使用的每个组件。然后通过this.props.store.
- 使用
react-redux's Provider,然后使用contextfor 组件来获取store.
可以想象,将 store 一直传递到组件是一场噩梦。
要首先使用storewith,context您需要指定contextTypes组件的 :
BookList.contextTypes = {
store: React.PropTypes.object.isRequired
};
这样做之后,您可以从中获取 storethis.context.store并使用它getState来获取状态或dispatch调度您的动作创建者。
如果我们不使用,我们的组件将会如何connect:
import React, { Component } from "react";
import { selectBook } from "../actions/index";
class BookList extends Component {
renderList() {
return this.context.store.getState().books.map( book =>
( <li
key={book.title}
onClick={() => this.context.store.dispatch( selectBook( book ))}
>
{book.title}
</li> ) );
}
render() {
return (
<ul>
{this.renderList()}
</ul>
);
}
}
BookList.contextTypes = {
store: React.PropTypes.object.isRequired,
};
export default BookList;
这里我们使用:this.context.store.getState().books代替this.props.books和this.context.store.dispatch( selectBook( book ))代替this.props.selectBook( book )。如您所见,我们可以通过这种方式到达状态并调度我们的动作创建者。但是凭借connect其灵活性,我们以一种漂亮而干净的方式打开我们的状态和动作创建器。