对react-Redux的利用与了解

在平时中,咱们间接去应用Redux,须要每个页面都须要引入store,执行getState()来获取到值,以及须要每次都进行订阅和勾销订阅。保护起来不不便

import React,{Component} from 'react'import store from '../store'export default class ReactRedux extends Component{  constructor(){    super()  }  componentDidMount(){// 挂载    this.unsubscribe=store.subscribe(()=>{      this.forceUpdate()    })  }  add=()=>{        store.dispatch({type:'ADD',payload:10})  }  componentWillUnmount(){// 卸载    if(this.unsubscribe){      this.unsubscribe()    }  }  render(){    return(      <div>        <h3>ReactRedux-page</h3>        <div>          <p>{store.getState()}</p>          <button            onClick={this.add}          >            add          </button>        </div>      </div>    )  }}
从而引入react-Redux,Provider这个性能;在根目录下间接引入store;

src/index.js

import React from 'react';import ReactDOM from 'react-dom';import './index.css';import ReactRedux from './pages/ReactReduxPage'import {Provider}  from 'react-redux'import store from './store'ReactDOM.render(  <Provider store={store}>    <ReactRedux />  </Provider> ,  document.getElementById('root'));

class组建在应用connect引入

import {connect} from 'react-redux'
connect一共有三个参数:state, dispatch,mergeProps(将props进行合并)
@connect(  (state)=>({num:state}))class ReactRedux extends Component{    render(){      console.log(this.props)      return(        <div></div>            )   }}
@connect是装璜器的应用,或者能够export default connect()(class ...);装璜器的应用能够本人查下不做重点解说。
打印this.props

能够看到 传进来的state值,以及dispatch;咱们能够在porps中拿到。
import React,{Component} from 'react'import store from '../store/'import {connect} from 'react-redux'@connect(  (state)=>({num:state}))class ReactRedux extends Component{  constructor(){    super()  }  add=()=>{        this.props.dispatch({type:'ADD',payload:10})  }  render(){    const {num, dispatch} = this.props    console.log(this.props,'this.props')    return(      <div>        <h3>ReactRedux-page</h3>        <div>          <p>{num}</p>          <button            onClick={this.add}          >            add          </button>        </div>      </div>    )  }}export default ReactRedux
点击的时候间接,间接更新状态;就不再须要去调用生命周期,应用redux的subscribe来进行订阅,更新状态。
connectmapDispatchToProps多种写法
dispatch 能够是对象 也能够是函数;

对象写法

@connect(  //store  (state)=>({num:state}),  // dispatch 类型:obj|fn  {    add:()=>({      type:'ADD',      payload:20    })  })

函数写法

  dispatch=>{    const add =()=>dispatch({ type:'ADD', payload:20})    const minus=()=>dispatch({type:'MINUS', payload:10})    return {dispatch,add ,minus}  }

或者应用import bindActionCreators from 'redux'

最初整合进去,的后果和下面的写法是一样的,只是上面应用 bindActionCreators来进行了整合
  dispatch=>{    // const add =()=>dispatch({ type:'ADD', payload:20})    // const minus=()=>dispatch({type:'MINUS', payload:10})    //这个写法和申明正文的写法是一样的    let creators={      add:()=>({type:'ADD', payload:20}),      minus:()=>({type:'MINUS', payload:10})    }    creators=bindActionCreators(creators, dispatch)    return {dispatch,...creators}  }

props将会上挂载了 add、minus 和dispatch办法;

应用:

 Dispatchadd=()=>{   this.props.dispatch({type:'ADD',payload:10}) }render(){  const {num, add,minus} = this.props  console.log(this.props,'this.props')  return(    <div>      <h3>ReactRedux-page</h3>      <div>        <p>{num}</p>        <button onClick={this.Dispatchadd}>Dispatchadd+10</button>        <button onClick={add}>add+20</button>             <button onClick={minus}>minus-10</button>      </div>    </div>  )

mapDispatchToProps 的总结
写法一: function间接能够将dispatch返回;

dispatch=>{// 在外面定义其余的disaptch办法return (dispatch, 其余dispatch办法)}

写法二: object 间接定义dispatch,然而组建中,就只能去调用定义的办法名字,不能去应用this.props.dispatch

 {   add:()=>({     type:'ADD',     payload:20   }) }
import React,{Component} from 'react'import {connect} from 'react-redux'import {bindActionCreators} from 'redux'@connect(  //将state放在props上一份;  `参数一: mapStateToProps`  (state)=>({num:state}),  `参数二:mapDispatchToProps`  // dispatch 类型:obj|fn 将 dispatch放在poros上一份; mapDispatchToProps  // dispatch写法一: 不含自身的dispatch,只能调用对象外面写的办法;  // {  //   add:()=>({  //     type:'ADD',  //     payload:20  //   })  // }  // dispatch 写法二:  (dispatch,ownProps)=>{   // ownProps 是指的,当传进来的props进行了批改,每一次都会加载一遍;   //ownProps 能够不写,写了只不过是每次当props批改的时候,就会调用这个办法      // 办法一:间接这样写,到导出    // const add =()=>dispatch({ type:'ADD', payload:20})    // const minus=()=>dispatch({type:'MINUS', payload:10})    // return {dispatch, add, minus}    // 办法二: 应用bindActionCreators 来进行合并    let creators={      add:()=>({type:'ADD', payload:20}),      minus:()=>({type:'MINUS', payload:10})    }    creators=bindActionCreators(creators, dispatch)    return {dispatch,...creators}  },  `参数三:mergeprops`,解说在最初,拿出来说,其实并不怎么罕用  (stateProps,dispatchProps,ownProps)=>{    return {      ...stateProps,      ...dispatchProps,      ...ownProps    }  })class ReactRedux extends Component{  constructor(){    super()  }  Dispatchadd=()=>{    this.props.dispatch({type:'ADD',payload:10})  }    render(){    const {num, add,minus} = this.props    console.log(this.props,'this.props')    return(      <div>        <h3>ReactRedux-page</h3>        <div>          <p>{num}</p>          <button onClick={this.Dispatchadd}>Dispatchadd+10</button>          <button onClick={add}>add+20</button>               <button onClick={minus}>minus-10</button>               </div>      </div>    )  }}export default ReactRedux
connectmergeprops应用阐明
 (stateProps,dispatchProps,ownProps)=>{   return {     ...stateProps,     ...dispatchProps,     ...ownProps   } }

打印 this.props的值

dispatch 和 state

当 在return 外面自定义了内容时,props的打印后果

 (stateProps,dispatchProps,ownProps)=>{   return {     ...stateProps,     ...dispatchProps,     ...ownProps,     own:'自定义内容'   } }

如果在 return外面删除 stateProps,或者dispatchProps;
this.props 也会随之缺失


mapDispatchToProps的函数写法上,去整合 dispatch引入了一个bindActionCreators,当初咱们本人实现一下试试。

实现bindActionCreators

import {bindActionCreators} from 'redux'

这个是redux的api,bindActionCreators的作用是将一个或多个action和dispatch组合起来生成mapDispatchToProps须要生成的内容。
function bindActionCreator(creator,dispatch){// console.log(creator,'creator')  return (...args) => {    console.log(args,'...args') // 函数在onClick 调用的时候传递进来的参数    dispatch(creator(...args))  }}// 接管两个参数 creators, dispatchexport function bindActionCreators(creators, dispatch){  console.log(creators,'creators')  // 定一个一个空的对象  let obj={} // 用来导出  // 首先须要遍历进去,给每一项加上dispatch;  for(let key in creators){    obj[key] = bindActionCreator(creators[key],dispatch)  }  console.log(obj,'obj')  return obj}

阐明:

  • bindActionCreators导出的还是一个对象,是用dispatch整合进去的对象。所以最初return obj
  • for...in 将每一个穿进来的对象,用dispatch在包一层
  • args 是从何而来?

    咱们当初批改add 叠加的形式:

       let creators={     add:(num)=>({type:'ADD',...num}),     minus:()=>({type:'MINUS', payload:10})   }

    num 是办法在调用的时候传进来的参数

    class ReactRedux extends Component{ render(){   const {num} = this.props   <button onClick={()=>{add({payload:20})}}>add+20</button>  }

    这个时候,咱们来打印看看,当初的agrs是什么?

    就是咱们在调用add 办法的时候传进来的参数

实现Provider

这个没什么就是用React.createContext();嵌套了一层。这样谈话的语气,显得好牛b呀,哈哈哈哈哈哈哈哈,牛死我了
import React from  'react'const Context= React.createContext()export function Provider({children, store}){return <Context.Provider value={store}>{children}</Context.Provider>}

实现commit

先搭建一个架子进去
import React from  'react'export const commit=(  mapStateToProps=state=>state, //这个就是state  mapDispatchToProps // 这个就是整个进去的dispatch)=>WrappedComponent=>props=>{ // 最初由组建+props,返回一个新的组建  return<WrappedComponent {...props}/>}
组建stateProps的获取
   // 首先要获取到传递进来的stateToProps   // state的获取是从mapStStateToProps而来的    const stateProps = mapStateToProps(这里的state从何而来)     //mapStateToProps 是一个函数传进来一个state,导出一个state;
mapStateProps的参数state如何获取
首先明确,咱们以后的组建,是一个函数组建
那函数组建如何获取state? 通过getState来获取,getState在store外面;联合上下文,咱们须要用到useContext来获取;
  // useContext 读取以后的Context;  const store = useContext(Context);  // 从store中去获取store  const {getState} =store  const stateProps = mapStateToProps(getState())  return<WrappedComponent {...props} {...stateProps}/>
实现 mapDispatchToProps

初始化曾经实现,还须要实现dispatch办法的实现
如何获取dispatch
咱们先打印下store

 // useContext 读取以后的Context; const store = useContext(Context); console.log('store外面的内容:', store)


从而得悉,dispatch能够从store中获取。
接下来思考如何更新;dispatch之后组建为更新,所以用订阅subscript 调用forceUpdate来更新组建
在函数组建中,咱们应用useReduce 来实现forceUpdate函数,在官网中有记录。
有相似 forceUpdate 的货色吗?:https://zh-hans.reactjs.org/d...

还须要主见一个问题,就是当咱们去订阅的时候,肯定要去勾销订阅
咱们在什么生命周期外面去调用订阅呢?

useEffect 还是 useLayoutEffect 中去应用?


看介绍能够得悉,useLayoutEffect的调用要比useEffect更为提前
useEffect 存在提早;如果组建在constructor中就有了订阅和更新,那么useEffect 就会失落。
所以咱们应用useLayoutEffect
const {getState, dispatch, subscribe} =storeconst dispatchProps={    dispatch  }  const [ignored, forceUpdate] = useReducer(x=>x+1,0)  useLayoutEffect(() => {  // 相当于 componentDidMount;useLayoutEffect要比useEffect要提前执行    // 订阅    const unsubscribe =subscribe(()=>{       forceUpdate()// 刷新状态    })    return () => { // 相当于 componentWillUnmount      // 勾销订阅      if(unsubscribe){         unsubscribe()      }    }  }, [store]) // 关联store变动时触发    return <WrappedComponent {...props} {...stateProps} {...dispatchProps}/>
实现mapDispatchToProps
  • 从下面的案例得悉,mapDispatchToProps有两种展示模式,一种是对象,一种是函数。
  • 咱们先打印看下当mapDispatchToProps是函数的状况,是什么?

所以 能够得出结论,如果是函数的时候,间接穿参dispatch,执行mapDispatchToProps函数就能够
  • 如果mapDispatchToProps是对象,打印后果
外面是一个对象,咱们只须要将它用bindActionCreators进行封装之后在返回就能够。
  let  dispatchProps={ // 定义变成let,上面会依据mapDispatchToProps来进行反复赋植    dispatch  }  // console.log('dispatchProps',dispatchProps);  // console.log('mapDispatchToProps',mapDispatchToProps)  // 首先进行类型的判断   if (typeof mapDispatchToProps === 'function') {     // 如果是函数,就将diapatch传进去,之后执行函数在返回      dispatchProps =mapDispatchToProps(dispatch)   } else if (typeof mapDispatchToProps === 'object'){     // 如果是对象,就调用bindActionCreators,将对象进行封装返回     dispatchProps =bindActionCreators(mapDispatchToProps,dispatch)   }

react-redux的实现残缺代码

门路:src/MyReactRedux.js

import React,{useContext,useReducer,useLayoutEffect} from  'react'import {bindActionCreators} from './MybindActionCreators'const Context= React.createContext()export const connect=(  mapStateToProps=state=>state,  mapDispatchToProps)=>WrappedComponent=>props=>{    // useContext 读取以后的Context;  const store = useContext(Context);  // 从store中去获取store  const {getState, dispatch, subscribe} =store  // 首先要获取到传递进来的stateProps  // state的获取是从mapStateToProps而来的  const stateProps = mapStateToProps(getState()) //mapStateToProps 是一个函数传进来一个state,导出一个state;  let  dispatchProps={ // 定义变成let,上面会依据mapDispatchToProps来进行反复赋植    dispatch  }  // console.log('dispatchProps',dispatchProps);  // console.log('mapDispatchToProps',mapDispatchToProps)  // 首先进行类型的判断   if (typeof mapDispatchToProps === 'function') {     // 如果是函数,就将diapatch传进去,之后执行函数在返回      dispatchProps =mapDispatchToProps(dispatch)   } else if (typeof mapDispatchToProps === 'object'){     // 如果是对象,就调用bindActionCreators,将对象进行封装返回     dispatchProps =bindActionCreators(mapDispatchToProps,dispatch)   }  const [ignored, forceUpdate] = useReducer(x=>x+1,0)  useLayoutEffect(() => {  // 相当于 componentDidMount;useLayoutEffect要比useEffect要提前执行    // 订阅    // console.log('useLayoutEffect')    const unsubscribe =subscribe(()=>{       forceUpdate()// 刷新状态    })    return () => { // 相当于 componentWillUnmount      // 勾销订阅      if(unsubscribe){         unsubscribe()      }    }  }, [store]) // 关联store变动时触发  return <WrappedComponent {...props} {...stateProps} {...dispatchProps}/>}export function Provider({children, store}){ return <Context.Provider value={store}>{children}</Context.Provider>}

学习材料

github:https://github.com/speak44/le...
分支是:react-redux