Reprinted note:
- The author is Ye Zhai of Taobao front-end team. I like this article very much, so I rearrange it and reprint it here. At the same time, I also add some of my own experience.
- Original address:http://taobaofed.org/blog/201…
Redux is one of the most important components of react. It tries to provide a predictable state management mechanism for react applications. Redux itself is simple enough to support other interface frameworks besides react. So if you want to use Redux and react together, you need some additional tools, the most important of which is react redux.
React Redux provides two important objects,Provider
andconnect
The former makesReact
The component can be connected, which connects the react component with the store of redux. In the document of react Redux, theconnect
When I first learned Redux, I read this document for a long time, but I didn’t understand all the meanings of it.
After using Redux for a period of time, this article tries to come back here again and give you some adviceThis is the documentA reliable interpretation.
Preparatory knowledge
First, let’s review the basic usage of redux. If you haven’t read the Redux document, you must go firstreadonce.
const reducer = (state = {count: 0}, action) => {
switch (action.type){
case 'INCREASE': return {count: state.count + 1};
case 'DECREASE': return {count: state.count - 1};
default: return state;
}
}
const actions = {
increase: () => ({type: 'INCREASE'}),
decrease: () => ({type: 'DECREASE'})
}
const store = createStore(reducer);
store.subscribe(() =>
console.log(store.getState())
);
store.dispatch(actions.increase()) // {count: 1}
store.dispatch(actions.increase()) // {count: 2}
store.dispatch(actions.increase()) // {count: 3}
adoptreducer
Create astore
Every time westore
upperdispatch
Oneaction
,store
The data in will change accordingly.
Of course, we can use Redux directly in react: initialize in the outermost container componentstore
, and thenstate
Properties on asprops
Pass it on layer by layer.
class App extends Component{
componentWillMount(){
store.subscribe((state)=>this.setState(state))
}
render(){
return (
<Comp
state={this.state}
onIncrease={()=>store.dispatch(actions.increase())}
onDecrease={()=>store.dispatch(actions.decrease())}
/>
)
}
}
Reprinted note:
- Another way is in the entry file
index.js
Initialization instore
, andexport
Come out, thenimport
Go to the file that defines the component.
But that’s not the best way. The best way is to use react reduxProvider
andconnect
method.
Using react Redux
First, in the outermost container, wrap everything in a containerProvider
Component, thestore
Asprop
Pass on toProvider
。
const App = () => {
return (
<Provider store={store}>
<Comp/>
</Provider>
)
};
Provider
Any of the components in theComp
), if necessarystate
The data in must be the “connected” componentconnect
Method for the “component you write”(MyComp
)After packaging.
class MyComp extends Component {
// content...
}
const Comp = connect(...args)(MyComp);
soconnect
Method is the top priority.
connect
Exactly?connect
What does the method do? Let’s explore it.
First, let’s look at the signature of the function
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
connect()
Receive four parameters, which aremapStateToProps
,mapDispatchToProps
,mergeProps
andoptions
。
mapStateToProps
mapStateToProps(state, ownProps) : stateProps
This function allows us tostore
Data in asprops
Bind to a component.
const mapStateToProps = (state) => {
return {
count: state.count
}
}
The first parameter of this function is reduxstore
And we’ve got something out of itcount
Property. Because returned withcount
Property, soMyComp
Will be known ascount
Ofprops
Field.
class MyComp extends Component {
render(){
Return < div > count:{ this.props.count }Times < / div >
}
}
const Comp = connect(...args)(MyComp);
Of course, you don’t have tostate
The data in is passed into the component intact, which can be changed according to thestate
To dynamically output the (minimum) attributes required by the component.
const mapStateToProps = (state) => {
return {
greaterThanFive: state.count > 5
}
}
The second argument to the functionownProps
YesMyComp
ownprops
. sometimes,ownProps
It will also have an impact on it. For example, when you arestore
A list of users is maintained in, and your componentsMyComp
Only care about one user (viaprops
InuserId
(embodiment).
const mapStateToProps = (state, ownProps) => {
//State is {userlist: [{ID: 0, name: 'Wang Er'}]}
return {
user: _.find(state.userList, {id: ownProps.userId})
}
}
class MyComp extends Component {
static PropTypes = {
userId: PropTypes.string.isRequired,
user: PropTypes.object
};
render(){
Return < div > User Name:{ this.props.user .name}</div>
}
}
const Comp = connect(mapStateToProps)(MyComp);
Whenstate
Change, orownProps
When things change,mapStateToProps
Will be called to calculate a newstateProps
In relation toownProps
After merge) update toMyComp
。
That’s how Reduxstore
The basic way to connect data in to components.
Reprinted note:
- What is it called“
MyComp
ownprops
”?Suppose you don’t use react redux,MyComp
The parent component of isParentComp
So the aboveownProps
yesParentComp
Pass on toMyComp
For the methods belowmapDispatchToProps
The same is true.in other words,ownProps
With Reduxstore
Andstate
Nothing at all。- method
mapStateToProps
byMyComp
The added property cannot be used by the methodmapDispatchToProps
Access to, and vice versa.Because, this involves the timing and order of render, the author has stepped on a lot of holes in it. As for why I have this demand, because I designed a button, the function is: after clicking, calculate the next state according to the current state, and update. I’ve been through a loterror
After that, I finally realized that react Redux is not designed to solve this kind of problem at all. There are two solutions: one is to update the reducer directly according to the state when designing it; the other is to import the global datastore
And usestore.getState()
Get currentstate
And then according to thisstate
Update.- In addition, if you usePropTypesyes
MyComp
Do attribute type check, methodmapStateToProps
And methodsmapDispatchToProps
byMyComp
The added property exists.
mapDispatchToProps
mapDispatchToProps(dispatch, ownProps): dispatchProps
The second parameter of connect ismapDispatchToProps
Its function is toaction
Asprops
Bind toMyComp
It’s on.
const mapDispatchToProps = (dispatch, ownProps) => {
return {
increase: (...args) => dispatch(actions.increase(...args)),
decrease: (...args) => dispatch(actions.decrease(...args))
}
}
class MyComp extends Component {
render(){
const {count, increase, decrease} = this.props;
return (<div>
< div > count:{ this.props.count }Times < / div >
< button onclick = {increase} > increase < / button >
< button onclick = {decrease} > reduce < / button >
</div>)
}
}
const Comp = connect(mapStateToProps, mapDispatchToProps)(MyComp);
becausemapDispatchToProps
Method returns aincrease
Attributes anddecrease
Property, these two properties also becomeMyComp
Ofprops
。
As shown above, callactions.increase()
Only oneaction
object{type:'INCREASE'}
To trigger thisaction
Must be instore
Call updispatch
method.dispatch
ExactlymapDispatchToProps
The first parameter of. However, in order not to be perceived by the mycomp componentdispatch
For the existence of the world, we need toincrease
anddecrease
Two functions are packaged to make them directly callable (that is, calling the method triggers adispatch
)。
Redux itself providesbindActionCreators
Function to set theaction
Packaged as a function that can be called directly.
import {bindActionCreators} from 'redux';
const mapDispatchToProps = (dispatch, ownProps) => {
return bindActionCreators({
increase: action.increase,
decrease: action.decrease
});
}
Again, whenownProps
When it changes, the function will also be called to generate a new onedispatchProps
In relation tostateProps
andownProps
After merge) update toMyComp
. be careful,action
The change of will not cause the above process, defaultaction
It is fixed in the life cycle of a component.
Reprinted note:
- function
connect
even to the extent thatreact-redux
The core of Redux is to bind the state of store in Redux to the properties of components, so that the modification of state can be directly reflected as the change of component appearance. Therefore, the parametermapStateToProps
It’s very important, but the parametersmapDispatchToProps
It’s superfluous – because simply and rudely importing the global store can also achieve the same purpose (in fact, this is what I do).
mergeProps
[mergeProps(stateProps, dispatchProps, ownProps): props]
As I said before, no matter whatstateProps
stilldispatchProps
We all need to talk to each otherownProps
Merge will be assigned toMyComp
。connect
The third parameter of is used to do this. Usually, you don’t need to pass this parameter,connect
Will useObject.assign
Instead of this method.
other
Finally, there’s another oneoptions
The options are relatively simple, and they are rarely used (especially when you follow some of the “best practices” of react). Hope to understand the students can directly look at the document.
(end)