2-react与 redux 的链接
屏幕快照 2018-06-26 下午4.28.00.png
步骤:
1. 下载
npm install --save react-redux
2、引入connect
import {connect} from 'react-redux'
connect是一个高阶组件:首先需要传一些数据过去,接着在运行完成之后会得到一个函数,这个函数就是一个高阶组件,通过这个函数将组件传进去你就会得到一个新的组件,这个所以这个文件最后需要导出的是connect。
3、引入react-redux
import {
Provider,
connect
} from 'react-redux'
4、将Provider放置在根元素
注意:必须要有一个child
ReactDOM.render(
<Provider>
<Counter></Counter>
</Provider>,
document.getElementById('root')
)
这个时候,在组件的render里面打印this.props,就可以得到dispatch,这就是真正的sotere.dispatch。
这个dispacth是谁传过来的?
是Provider,通过props绑定了store,通过store.dispatch得到了一个方法,得到这个方法之后,绑定到了connect的API上,props是一级一级传递。
5、connect
connect([mapStateToProps],[mapDispatchToProps])
//通过字面意思可以理解:第一个参数是将state传到了props,第二个参数是将dispatch传到了props
第一个参数:函数,里面必须return一个对象。
在这第一个参数的函数里,return出来了什么,这个组件的props就会得到什么。
这个时候在控制台打印this.props,就会得到:{a: 1, b: 2, dispatch: ƒ}
export default connect(
()=>{
return {
a:1,
b:2
}
}
)(Counter)
我们再传入第二个参数:
export default connect(
()=>{
return {
a:1,
b:2
}
},
()=>{
return {
c : 888
}
}
)(Counter)
这时候控制台打印props,得到 : {a: 1, b: 2, c: 888},可以看到:dispatch没有了,但是这时候定义的c:888被组合到了props里面。
这样做有什么意义?意义就在于接收的参数,第一个函数的参数是state,这就是store.getState()的state,第二个函数的参数是dispatch,就是dispatch一个action的,也就是第一个参数是getState拿数据,第二个参数是dispatch改数据,
如何提交action呢?
6、
新建一个文件,里面放置action,并将这几个action导出(只要actionCreators)。
如果某个actionCreator是通过中间件创建的,那么得到的就是一个函数,而不是一个对象,所以这时候如果想用这个actionCreator,就需要引入中间件,比如以下下面这个actionCreator:
let increaseByAsyncAction = (val)=>(dispatch,getState)=>{
setTimeout(()=>{
dispatch(decreaseAction(val))
},1000)
}
这时候就需要在index,即需要提交action的文件里引入redux-thunk
import thunk from 'redux-thunk'
const store = createStore(counter,0,applyMiddleware(thunk),0)
7、使用react-redux提交aciton
render(){
console.log(this.props)
//第一步,首先需要取出state和dispatch
let {count,dispatch} = this.props
return(
<div>
<button className="decrease"
//然后就可以dispatch对应的action
onClick={()=>{
dispatch(countActions.decreaseAction(1))
}}>-</button>
<span>{count}</span>
<button className="increase"
onClick={()=>{
dispatch(countActions.increaseAction(1))
}}
>+</button>
<button className="odd">in by odd</button>
<button className="async">in by async</button>
</div>
)
}
疑问?监听器在哪里执行的
其实是写在了Provider里面,这个组件绑定了props:strore,这是最顶层的组件,一旦监听到state的变化,就会setState,然后所有的子组件都会更新,这时候就得到了新的props状态。所以这就是把Provider写在最顶层的原因。
8、简写
现在写了很多手动提交的dispatch,有没有一种方法而已简写呢?
- 引入
import {bindActionCreators} from 'redux'
// 已经绑定好了action,所以直接b.decreaseAction即可,返回一个对象{decreaseAction,increaseAction}
let b = bindActionCreators(countActions,dispatch)
<button className="decrease"
onClick={()=>{
b.decreaseAction(1)
}}>-</button>
- 可以将这个bindActionCreators传到第二个参数函数中,这样就会发送到props,就可以解构直接使用了。
export default connect(
(state)=>{ //store.getState()
return {
count : state
}
},
(dispatch)=>bindActionCreators(countActions,dispatch)
)(Counter)
let {count,decreaseAction,increaseAction} = this.props
import React,{Component} from 'react'
import {connect} from 'react-redux'
import countActions from '../actions/countAction'
import {bindActionCreators} from 'redux'
class Counter extends Component{
constructor(props){
super(props)
}
render(){
console.log(this.props)
let {count,decreaseAction,increaseAction} = this.props
// 已经绑定好了action,所以直接b.decreaseAction即可,返回一个对象{decreaseAction,increaseAction}
//let b = bindActionCreators(countActions,dispatch)
return(
<div>
<button className="decrease"
onClick={()=>{
decreaseAction(1)
}}>-</button>
<span>{count}</span>
<button className="increase"
onClick={()=>{
increaseAction(1)
}}
>+</button>
<button className="odd">in by odd</button>
<button className="async">in by async</button>
</div>
)
}
}
export default connect(
(state)=>{ //store.getState()
return {
count : state
}
},
(dispatch)=>bindActionCreators(countActions,dispatch)
)(Counter)