前言
本文章的内容,不会对根底的Hook API进行解说,比方(能够从官网间接看到)
react Hook API:https://zh-hans.reactjs.org/d...
- useState
- useEffect
- useContext
间接放一个demo,自行学习吧。也不是很难
import React,{ useState,useEffect } from 'react'export default function HookPage(){ const [date, setDate]=useState(new Date()) const [count, setCount] = useState(0) // 一个函数能够有多个 useEffect useEffect(() => { console.log('数字产生扭转:' ,count) }, [count]); // 有依赖项,是count; 所以每次点击更改count的时候进行更新,就相当于生命周期update useEffect(()=>{ console.log('setDate') const timer = setInterval(()=>{ setDate(new Date()) },1000) // 革除定时器,相当于申明周期 willUnmount return()=>clearInterval(timer) },[]) // 没有依赖项,就相当于DidMount return( <div> <h3> HookPage </h3> <div> <span> 数字:{count} </span> <button onClick={()=>setCount(count+1)}>减少</button> </div> <div> 当初工夫:{date.toLocaleTimeString()} </div> </div> )}
所有的react API 在官网都说的很不错了,我感觉看官网的介绍就曾经很明确了,而且迭代版本必定也是最新的,所以本章的内容次要是联合实战和我的项目,进行简略的应用阐明,之后在进行,手动实现react-redux的Hook API;
useReducer
略微说下这个API,因为 我在应用init
的时候,忽略了一个return,导致我查了半天。
import React,{useReducer,useEffect} from 'react'const creatReduce=(state,{type,payload=1})=>{ switch (type) { case 'ADD': return state+payload case 'MINUS': return state-payload case 'reset': return init(payload) // 这里曾经要加return,要不然里面的state拿不到批改后的state default: return new Error() }}function init(payload) { console.log('payload',payload); return payload; }export default function HookPage2(){ const [state, dispatch] = useReducer(creatReduce, 0, init) // console.log(creatReduce,'creatReduce') useEffect(() => { console.log('useEffect',state) }, [state]) return( <div> <h3> HookPage2 </h3> <div> {state} </div> <button onClick={()=>{dispatch({type:'ADD'})}}>点击减少</button> <button onClick={()=>{dispatch({type:'reset' ,payload:6})}}>重置state</button> <button onClick={()=>changeswitch()}>swtich变动</button> </div> )
接下来,咱们看函数组建如何应用connect
react 的函数组建,定义组建名大写,外面有return(<div></div>)
hook API
useSelctor获取到store state
useDispatch获取dispatch
import React,{useCallback} from 'react'import {useSelector, useDispatch} from 'react-redux'export default function ReactReduxHookPage(){ const num = useSelector(state => state) const dispatch = useDispatch() const add=useCallback( ()=>{ dispatch({type:'ADD'}) },[] ) console.log(num,'num') return( <div> <h3> ReactReduxHookPage </h3> <div> {num} </div> <button onClick={add}>add</button> </div> )}
useCallback
用于缓存inline
函数,缓存函数;避免因属性更新时生成新的函数导致子组件反复渲染
接下来咱们来实现自定义hook办法
还是写在门路:src/MyReactRedux.js
中
实现 useSelctor
咱们先来一个根本搭建
const Context= React.createContext()export function useSelector(){ // 首先要获取到store;用自定义的办法来获取context的值;用useContext}// 自定义hook,来获取stateexport function useStore(){ // 须要use结尾,大写字母;不能自己瞎定义自定义hook的名字 const store =useContext(connect)}
完整版的实现:
// 应用的办法const num = useSelector(state => state) // 先将参数传进来export function useSelector(selector){ // 首先要获取到store;用自定义的办法来获取context的值;用useContext // 最终须要实现的是getState //1.获取到store const store =useStore() //2.从store中获取到 getState console.log('useSelector的store', store) const {getState} = store // 获取到state 进行返回;selector传进来的是一个函数 ‘state => state’;getState()将作为selector函数的参数进行返回 const selectState = selector(getState()) //getState()的执行,是返回以后的state console.log('selectState:',selectState) return selectState}// 自定义hook,来获取stateexport function useStore(){ // hook的定义方法,须要use结尾,大写字母 const store =useContext(Context) return store}
让咱们看下打印后果:获取到了以后的值。
实现 useDispatch
根本搭建
export function useDispatch(){}
首先先明确useDispatch的返回值:
// 咱们的应用形式:const dispatch = useDispatch()export function useDispatch(){ // 指标是返回一个dispatch办法 // 1.先获取dispatch const store =useStore() // 间接返回 return store.dispatch}// 自定义hook,来获取stateexport function useStore(){ // hook的定义方法,须要use结尾,大写字母 const store =useContext(Context) return store}
当初咱们这样写useDispatch,当咱们点击页面的点击事件‘add'的时候,会发现,页面是没有变动的。是因为咱们触发了dispatch,却没有驱动页面进行刷新来进行批改。所以会存在页面没有刷新的状况。所以咱们还须要在useSelector中去订阅,当state变动的时候进行页面回流。
实现 加强版的useSelctor
,订阅和勾销订阅
// 应用的办法const num = useSelector(state => state) // 先将参数传进来export function useSelector(selector){ // 首先要获取到store;用自定义的办法来获取context的值;用useContext // 最终须要实现的是getState //1.获取到store const store =useStore() //2.从store中获取到 getState console.log('useSelector的store', store) const {getState,subscribe} = store const selectState = selector(getState()) //getState()的执行,是返回以后的state // 定义 forceUpdate const [ignored, forceUpdate] = useReducer(x=>x+1,0) // 当 store 批改的时候,调用useLayoutEffect; useLayoutEffect(() => { const unsubscribe =subscribe(()=>{ forceUpdate() }) return () => { if(unsubscribe){ unsubscribe() } }; },[store]) // 获取到state 进行返回;selector传进来的是一个函数 ‘state => state’;getState()将作为selector函数的参数进行返回 console.log('selectState:',selectState) return selectState}
useLayoutEffect 的应用和介绍官网有,我的上一篇文章
react-Redux的API的应用及原理解说和手动实现办法
也有具体的阐明和介绍;就是将react-redux的组建API和Hook API进行了离开解说。能够对照着来学习
hook的益处
自定义hook的益处就是能够共享逻辑,实现逻辑的复用 还须要留神hook办法只能用到hook办法当中去或者是函数组建中。本人写一个函数去应用hook是不能够的;
MyReactRedux的残缺版本
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>}// 应用的办法const num = useSelector(state => state) // 先将参数传进来export function useSelector(selector){ // 首先要获取到store;用自定义的办法来获取context的值;用useContext // 最终须要实现的是getState //1.获取到store const store =useStore() //2.从store中获取到 getState console.log('useSelector的store', store) const {getState,subscribe} = store const selectState = selector(getState()) //getState()的执行,是返回以后的state // 定义 forceUpdate const [ignored, forceUpdate] = useReducer(x=>x+1,0) // 当 store 批改的时候,调用useLayoutEffect; useLayoutEffect(() => { const unsubscribe =subscribe(()=>{ forceUpdate() }) return () => { if(unsubscribe){ unsubscribe() } }; },[store]) // 获取到state 进行返回;selector传进来的是一个函数 ‘state => state’;getState()将作为selector函数的参数进行返回 console.log('selectState:',selectState) return selectState}// 咱们的应用形式:const dispatch = useDispatch()export function useDispatch(){ // 指标是返回一个dispatch办法 // 1.先获取dispatch const store =useStore() // 间接返回 return store.dispatch}// 自定义hook,来获取stateexport function useStore(){ // hook的定义方法,须要use结尾,大写字母 const store =useContext(Context) return store}// 自定义hook的益处就是能够共享逻辑,实现逻辑的复用 还须要留神hook办法只能用到hook办法当中去或者是函数组建中。本人写一个函数去应用hook是不能够的;