React-Redux 中的 actionCreator、props 和组件是如何连接的? [英] How does the actionCreator, props, and component connect in React-Redux?
问题描述
我有这个代码:
import React, { Component } from 'react';从'react-redux'导入{连接};//这是一个连接属性import { selectBook } from '../actions/index';从redux"导入 { bindActionCreators };类 BookList 扩展组件 {渲染列表(){返回 this.props.books.map(book => {返回 (<li key={book.title} className="list-group-item">{book.title} </li>);});}使成为() {返回 (<ul className="list-group col-sm-4">{this.renderList()})}}函数 mapStateToProps(state) {返回 {书籍:state.books}}函数 mapDispatchToProps(dispatch) {//无论何时调用 selectBook,结果都应该传递给所有的 reducer.//selectBook 值是一个 actionCreator,一个函数.return bindActionCreators({ selectBook: selectBook }, dispatch)}导出默认连接(mapStateToProps,mapDispatchToProps)(BookList)
和
导出函数 selectBook(book) {console.log("已找到一本书:", book.title)}
我不明白的部分是这样的:
connect(mapStateToProps, mapDispatchToProps)(BookList)
这是怎么回事?这部分是否负责使组件BookList
可以使用状态和调度方法?
这个函数是做什么的:
function mapDispatchToProps(dispatch) {//无论何时调用 selectBook,结果都应该传递给所有的 reducer.//selectBook 值是一个 actionCreator,一个函数.return bindActionCreators({ selectBook: selectBook }, dispatch)}
这些是内置在 redux 函数中的吗?他们返回什么?到底是怎么回事?什么是dispatch
?
右边的值selectBook
是一个函数吧?所以我猜它被调用了,返回值将通过 dispatch 方法流经 reducer?但是,bindActionCreators
在做什么?
如何在 BookList
组件中提供 props?
你的问题太多了,我们试图解释它的努力可能会让你更加困惑.我强烈建议您观看 Redux 创建者的这两个视频:
那些视频解释了什么是 Redux,它的各个部分是如何组合在一起的.因此,在学习任何其他教程之前,请先了解 Redux 本身.
此外,Redux 的官方文档 很棒,如果您将其与视频一起使用,将非常适合你的学习.
但是,不管怎样,让我回答你的问题.
第一个问题
<块引用>我不明白的部分是这样的:
connect(mapStateToProps, mapDispatchToProps)(BookList)
<块引用>
这是怎么回事?这部分是否负责使状态和组件 BookList 可用的 dispatch 方法?
回答
connect
这里是由 react-redux
包提供的,而不是 redux
本身.它是一个辅助高阶函数,用于向组件打开状态和动作创建器.所以,你猜对了.这就是人们通常将他们的组件连接到商店以获取状态和分派(以使用动作创建者)的方式.
第二个问题
function mapDispatchToProps(dispatch) {//无论何时调用 selectBook,结果都应该传递给所有的 reducer.//selectBook 值是一个 actionCreator,一个函数.return bindActionCreators({ selectBook: selectBook }, dispatch)}
<块引用>
这些是内置在 redux 函数中的吗?他们返回什么?什么是继续?什么是派遣?
右边的值 selectBook 是一个函数吧?所以我猜它被调用,返回值将流经减速器通过调度方法?但是 bindActionCreators 在做什么?
道具如何在组件 BookList 中可用?
回答
不,它们不是像我在第一个答案中解释的那样内置于 Redux 函数中.mapStateToProps
将您的状态打开给您的组件并将其作为道具提供.因此,如果您使用 connect
和 mapStateToProps
打开组件的任何状态,您将获得该状态作为道具.在您的示例中,您从全局状态中获取 books
状态并将其作为 books
打开到您的组件.然后这个组件将其作为 this.props.books
.
mapDispatchToProps
将您的动作创建器函数作为道具打开给您的组件.有几种方法可以使用它,bindActionCreators
是其中之一,但实际上您在这里不需要它.如果您在将动作创建者分派或传递给不知道 Redux 的子组件时需要它,则可以获取状态.所以,bindActionCreators
并不是理解 mapDispatchToProps
的好开始.
基本上是这样的:
const mapDispatchToProps = dispatch =>({someFunction: () =>调度(someFunction())})
在这里,您将向组件打开 someFunction()
动作创建器,名称为 someFunction
.您可以使用不同的名称,也可以在这里做其他人员,然后根据此dispatch
您的动作创建者.但是在这个例子中,你没有做任何额外的事情,只是调度动作创建者.所以,这里有一个简写:
const mapDispatchToProps = {一些功能,}
是的,对于这种情况,这会做同样的事情.甚至,还有一个更短的:
connect(mapStateToProps, {someFunction})(Component)
不使用 mapDispatchToProps
你可以像这样使用你的动作创建器,然后在你的组件中作为道具.
此外(是的,还有更多:))在连接中不使用任何函数参数的事件,我们可以使用动作创建者.
connect()(组件)连接(mapStateToProps)(组件)
如果我们像上面的方法之一一样跳过 mapDispatchToProps
,dispatch
会自动传递给组件 props.然后,我们可以像使用任何其他道具一样使用它来调度我们的动作创建者:
this.props.dispatch(someFunction())
对于你的例子,它是这样的(我知道这个应用程序,所以我在这里使用真实动作创建者的例子).
你可以这样写mapDispatchToProps
:
const mapDispatchToProps = dispatch =>( {选择书:书 =>调度(选择书(书)),});
在这里,您在组件中使用 selectBook
作为 this.props.selectBook
并分派一个动作.你实际上看到你的道具触发了一个函数,它在这里调度你的真实动作创建者.请记住,动作创建者返回对象,这些对象需要被分派才能通过 reducer.因此,您正在调度您的操作创建者(由 selectBook
返回.
现在,使用 bindActionCreators
而不使用它的真正优势,您可以将其编写为:
const mapDispatchToProps = dispatch =>(bindActionCreators( { selectBook: selectBook }, dispatch ));
或者使用 ES6 中具有相同名称的对象键的一些简写:
const mapDispatchToProps = dispatch =>(bindActionCreators( { selectBook }, dispatch ));
这比第一个略短.你不需要指向一个函数并调度它.您将动作创建者交给 bindActionCreators
,它会为您完成工作.
现在,由于您只是在调度,因此较短:
const mapDispatchToProps = {选择书,};
即使没有mapDispatchToProps
:
connect( mapStateToProps, { selectBook } )( BookList )
所以,Provider
、connect
由 react-redux
提供,让我们的生活更轻松.mapStateToProps
和 mapDispatchToProps
是 connect
等待的函数.名称并不重要,我们可以为它们使用任何名称,但这些是每个人都使用的事实上的名称.顺序很重要,如果我们想跳过 mapStateToProps
,我们必须在它的位置使用 null
,例如:
connect( null, mapDispatchToProps )( 组件 )
没有 connect
实际上我们可以使用 store
和它包含的内容 getState
, dispatch
, subscribe
在任何组件中有两种方式:
- 不要使用
react-redux
并将store
作为 prop 一直传递到您要使用的每个组件.然后通过this.props.store
访问它. - 使用
react-redux
的Provider
,然后使用context
为组件获取store
.
正如您所想象的那样,将 store 一直传递到组件是一场噩梦.
要使用 store
和 context
首先你需要指定组件的 contextTypes
:
BookList.contextTypes = {商店:React.PropTypes.object.isRequired};
之后你可以从 this.context.store
获取 store 并使用 getState
获取状态或 dispatch
来调度你的动作创作者.
如果我们不使用connect
,我们的组件会是什么样子:
import React, { Component } from "react";import { selectBook } from "../actions/index";类 BookList 扩展组件 {渲染列表(){返回 this.context.store.getState().books.map( book =>( <li键={书名}onClick={() =>this.context.store.dispatch( selectBook( book ))}>{书名}) );}使成为() {返回 (<ul>{this.renderList()});}}BookList.contextTypes = {商店:React.PropTypes.object.isRequired,};导出默认书单;
这里我们使用:this.context.store.getState().books
而不是 this.props.books
和 this.context.store.dispatch( selectBook( book ))
而不是 this.props.selectBook( book )
.如您所见,我们可以通过这种方式到达状态并调度我们的动作创建者.但是通过 connect
及其灵活性,我们可以以一种简洁明了的方式打开我们的状态和动作创建器.
I have this code:
import React, { Component } from 'react';
import { connect } from 'react-redux'; //this is a single connect property
import { selectBook } from '../actions/index';
import { bindActionCreators } from 'redux';
class BookList extends Component {
renderList() {
return this.props.books.map(book => {
return (
<li key={book.title} className="list-group-item"> {book.title} </li>
);
});
}
render() {
return (
<ul className="list-group col-sm-4">
{this.renderList()}
</ul>
)
}
}
function mapStateToProps(state) {
return {
books: state.books
}
}
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)
}
export default connect(mapStateToProps, mapDispatchToProps)(BookList)
and
export function selectBook(book) {
console.log("A book has been seelcted:", book.title)
}
The parts that I don't understand are this:
connect(mapStateToProps, mapDispatchToProps)(BookList)
What is going on? Is this part responsible for making the state and the dispatch method available to the component BookList
?
What is this function doing:
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)
}
Are these built in redux functions? What are they returning? What is going on? What is dispatch
?
The value selectBook
on the right side is a function right? So I guess it gets called, and the return value will flow through the reducers via the dispatch method? But then what is bindActionCreators
doing?
How are props made available inside the component BookList
?
You have too many questions and how hard we try to explain it what is going on here probably confuses you more. I strongly advise you to watch those two videos from the creator of Redux:
Getting started with Redux and Idiomatic Redux
Those vidoes explain what is Redux, how does its pieces get together. So, before following any other tutorials first grasp Redux itself.
Also, Redux's official documentation is great, if you follow it alongside with the videos would be great for your study.
But, let me answer your questions anyway.
First question
The parts that I don't understand are this:
connect(mapStateToProps, mapDispatchToProps)(BookList)
What is going on? Is this part responsible for making the state and the dispatch method available to the component BookList?
Answer
connect
here is provided by react-redux
package, not redux
itself. It is a helper higher order function used to open your state and action creators to your components. So, you guessed right. This is how people generally connect their components into the store to get state and dispatch (to use action creators).
Second question
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)
}
Are these built in redux functions? What are they returning? What is going on? What is dispatch?
The value selectBook on the right side is a function right? So I guess it gets called, and the return value will flow through the reducers via the dispatch method? But then what is bindActionCreators doing?
How are props made available inside the component BookList?
Answer
No, they are not built in Redux functions as I explained in the first answer. mapStateToProps
opens your state to your component and feed it as props. So, if you open any state to your component with connect
and mapStateToProps
you get this state as props. In your example you get the books
state from your global state and open this as books
to your component. Then this component gets this as this.props.books
.
mapDispatchToProps
opens your action creator functions to your component as props. There a couple of ways using this, bindActionCreators
is one of them but actually you don't need it here. It is good for getting state if you need it while you are dispatching or passing your action creators to a child component which does not aware of Redux. So, bindActionCreators
is not a good start to understand mapDispatchToProps
.
Basically it is like that:
const mapDispatchToProps = dispatch => ({
someFunction: () => dispatch(someFunction())
})
Here you are opening your someFunction()
action creator to your component as the name someFunction
. You can use a different name or you can do other staff here and then dispatch
your action creator according to this. But in this example you are not doing anything extra, just dispatching the action creator. So, there is a shorthand for this:
const mapDispatchToProps = {
someFunction,
}
Yes, for this situation this does the same thing. Even, there is a shorter one:
connect(mapStateToProps, {someFunction})(Component)
Without using a mapDispatchToProps
you can use your action creators like this, then get as props in your components.
Also (yes there is more :)) event without using any function argument in connect, we can use action creators.
connect()(Component)
connect(mapStateToProps)(Component)
If we skip mapDispatchToProps
like one of the methods above, dispatch
is automatically passed to the component props. Then, we can use it like any other prop to dispatch our action creator:
this.props.dispatch(someFunction())
For your example it goes like this (I know this app, so I'm using real action creator example here).
You can write mapDispatchToProps
like this:
const mapDispatchToProps = dispatch => ( {
selectBook: book => dispatch( selectBook( book ) ),
} );
Here you use selectBook
as this.props.selectBook
in your component and dispatch an action. You see actually your prop fires a function and it dispatches your real action creator here. Remember, action creators returns objects and those objects need to be dispatched in order to go through reducers. So, you are dispatching your action creator (which is returned by selectBook
.
Now, with bindActionCreators
without using its real advantages you can write it as:
const mapDispatchToProps = dispatch => (
bindActionCreators( { selectBook: selectBook }, dispatch )
);
or with some ES6 shorthand for object keys which has the same name:
const mapDispatchToProps = dispatch => (
bindActionCreators( { selectBook }, dispatch )
);
This is slightly shorter than the first one. You don't need to point a function and dispatch it. You gave the action creator to bindActionCreators
and it does the job for you.
Now, the shorter one since you are just dispatching:
const mapDispatchToProps = {
selectBook,
};
Even without mapDispatchToProps
:
connect( mapStateToProps, { selectBook } )( BookList )
So, Provider
, connect
are being provided by react-redux
to make the life easier for us. mapStateToProps
and mapDispatchToProps
are the functions which connect
waits. Names are not important, we can use any name for them but these are the defacto ones everyone uses. The order is important and if we want to skip mapStateToProps
we must use null
in its place like:
connect( null, mapDispatchToProps )( Component )
Without connect
actually we can use store
and what it contains getState
, dispatch
, subscribe
in any component with two ways:
- Don't use
react-redux
and pass thestore
as prop all the way down to each component you want to use. Then reach it viathis.props.store
. - Use
react-redux
'sProvider
, then usecontext
for the component to get thestore
.
As you can imagine passing the store all the way down to components is a nightmare.
To use store
with context
first you need to specify the contextTypes
of the component:
BookList.contextTypes = {
store: React.PropTypes.object.isRequired
};
After doing that you can grab store from this.context.store
and use getState
to get the state or dispatch
to dispatch your action creators.
Here how our component would be if we didn't use 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;
Here we use: this.context.store.getState().books
instead of this.props.books
and this.context.store.dispatch( selectBook( book ))
instead of this.props.selectBook( book )
. As you can see we can reach state and can dispatch our action creators with this way. But with connect
and its flexibility we open our state and action creators in a nice and clean way.
这篇关于React-Redux 中的 actionCreator、props 和组件是如何连接的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!