一、React-Redux简介
学过聪明组件和傻瓜组件的我们知道,在开发一个项目时,如果每次都将一个组件拆成聪明组件和傻瓜组件,显然工作量巨大,那么对于很多个组件,他们每个都有一个聪明组件,如果,聪明组件基本逻辑相似,我们便可以将其统一的定义成一个组件,即提取相同的框架思想,于是便有了react-redux库。
1.Provider
Provider是整个应用最外层的React组件,它接受一个{store}作为参数props,内部挂载App组件,这样,store便可被其他所有组件访问到
// Provider源码
export default class Provider extends Component{
getChildContext(){
return {
store:this.store
}
}
constructor(props,context){
super(props,context)
this.store=props.store
}
render(){
const{children}=this.props
return Children.only(children)
}
}
具体详见图灵《深入React技术栈》
2.connect
connect函数本身返回名为wrapWithConnect的函数,这个函数是用来装饰React的,connect传入4个参数:
1.mapStateToProps
这是connect的第一个参数,它决定了我们要从redux状态树中提取哪些部分当作props传递给当前组件。如果不传入这个参数,则React组件将不会和Redux的状态树产生任何关系,
2.mapDispatchToProps
第二个参数接受store‘的dispatch作为第一个参数,,同时接受this.props作为可选的第二个参数。
3.mergeProps
4.options
二、例1:按钮点击数字改变
点击按钮视图发生改变
初步代码如下:此时connect只传入了一个参数,
//index.js (简单定义store,传入Provider注入)
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {createStore} from 'redux'
import {Provider} from 'react-redux'
const reducer=function(state,action){
switch(action.type){
case "ADD":{
return {
...state,
count:action.count
}
}
default:{
return state
}
}
}
const store=createStore(reducer,{count:0,color:'red'})
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App></App>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
// Provider源码
// export default class Provider extends Component{
// getChildContext(){
// return {
// store:this.store
// }
// }
// constructor(props,context){
// super(props,context)
// this.store=props.store
// }
// render(){
// const{children}=this.props
// return Children.only(children)
// }
// }
//App.js (connect传参)
import React,{Component} from 'react'
import {connect} from 'react-redux'
class App extends Component{
constructor(props){
super(props)
}
render(){
console.log(this.props)
const {count,color,dispatch} =this.props
return(
<div>
<h3 style={{color:color}}>{count}</h3>
<button onClick={()=>{dispatch({type:'ADD',count:2})}}>Add</button>
</div>
)
}
}
var mapStateToProps=function(state){
return{
count:state.count,
color:state.color
}
}
export default connect(mapStateToProps)(App);
由上面可知使用react-redux过程:
//1.创建store
//2.将store通过Provider注入
//3.connect连接Provider
//4.mapStateToProps函数获取所需要的状态
到此为止我们发现,与单纯使用redux 和react相比,我们少了一步渲染,即:
原因在于connect的源码中已经涉及到了相关同步渲染。源码过于复杂,此处百度。所以不需要额外处理即可同步更新视图部分。
这里还有一步,即connect的第二个参数
//5.mapDispatchToProps函数告诉Provider要分给什么函数
//告诉privider应该传过来什么函数
即根据自己定义的规则将函数名传递下去。修改后代码如下:
//App.js
import React,{Component} from 'react'
import {connect} from 'react-redux'
class App extends Component{
constructor(props){
super(props)
}
render(){
console.log(this.props)
const {count,color,add} =this.props
return(
<div>
<h3 style={{color:color}}>{count}</h3>
<button onClick={()=>{add()}}>Add</button>
</div>
)
}
}
var mapStateToProps=function(state){
return{
count:state.count,
color:state.color
}
}
var mapDispatchToProps=function(dispatch) {
return {
add(){
dispatch({
type:"ADD",
count:2
})
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(App);
三、例2:主题颜色改变
在文件外部写一个Theme组件,点击按钮改变主题颜色
//Theme.js
import React,{Component} from 'react'
import {connect} from 'react-redux'
class Theme extends Component{
render(){
console.log(this.props)
var {color,changeColor,dispatch}=this.props
return (
<div>
<h2 style={{color:color}}>Theme</h2>
<button onClick={()=>{changeColor('pink')}}>Pink</button>
<button onClick={()=>{changeColor('green')}}>Green</button>
</div>
)
}
}
var mapStateToProps=function(state) {
return {
color:state.color
}
}
var mapDispatchToProps=function(dispatch) {
return {
changeColor(e){
dispatch({
type:"CHANGE_COLOR",
color:e
})
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(Theme);
//App.js
import React,{Component} from 'react'
import {connect} from 'react-redux'
import Theme from './Theme'
class App extends Component{
constructor(props){
super(props)
}
render(){
console.log(this.props)
const {count,color,add} =this.props
return(
<div>
<h3 style={{color:color}}>{count}</h3>
<Theme></Theme>
<button onClick={()=>{add()}}>Add</button>
</div>
)
}
}
var mapStateToProps=function(state){
return{
count:state.count,
color:state.color
}
}
var mapDispatchToProps=function(dispatch) {
return {
add(){
dispatch({
type:"ADD",
count:2
})
}
}
}
export default connect(mapStateToProps,mapDispatchToProps)(App);
//index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import {createStore} from 'redux'
import {Provider} from 'react-redux'
const reducer=function(state,action){
switch(action.type){
case "ADD":{
return {
...state,
count:action.count
}
}
case "CHANGE_COLOR":{
return {
...state,
color:action.color
}
}
default:{
return state
}
}
}
const store=createStore(reducer,{count:0,color:'red'})
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App></App>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
// Provider源码
// export default class Provider extends Component{
// getChildContext(){
// return {
// store:this.store
// }
// }
// constructor(props,context){
// super(props,context)
// this.store=props.store
// }
// render(){
// const{children}=this.props
// return Children.only(children)
// }
// }