step1: 先创建一个Context对象
const Context = react.createContext()
step2: 通过Provider组件传递context value
export function Provider({children,store}){
return <Context.Provider value={store}>{children}</Context.Provider>
}
step3: 子组件接收context value
- connect 是个hoc,接收组件作为参数,然后返回一个新组件
- 新的组件上可以是由你选择映射state和dispatch
export const connect = (
mapStateToProps = state=>state,
mapDispatchToProps //数据类型是undefined,object,function
)=>WrappedComponent=>props=>{
// 首先获取store
const store = useContext(Context)
// 获取state的函数
const {getState, dispatch, subscribe} = store
const stateProps = mapStateToProps(getState())
let dispatchProps = {}
if(typeof mapDispatchToProps ==="function"){
dispatchProps = mapDispatchToProps(dispatch)
}else if(typeof mapDispatchToProps === "object"){
dispatchProps = bindActionCreators(mapDispatchToProps,dispatch)
}else{
dispatchProps = {dispatch}
}
return <WrappedComponent {...props} {...dispatchProps} {...stateProps} />
}
const forceUpdate = useForceUpdate()
useLayoutEffect(()=>{
const unsubscribe = store.subscribe(()=>{
forceUpdate();
})
return ()=>{
if(unsubscribe){
unsubscribe()
}
}
},[store])
函数组件怎么实现类似forceUpdate的方法
function useForceUpdate(){
const [state,setState] = useState(0)
const update = useCallback(()=>{
setState(prev=>prev+1)
},[])
return update
}
const forceUpdate = useForceUpdate()
这里用useLayoutEffect而不是useEffect的原因
- useEffect在组件更新完之后有延迟,有可能会漏掉一些订阅
- useLayoutEffect是渲染之后同步执行,useEffect是异步批量执行
react-redux Hook
- useSelector(({count})=>count): 拿到整个state数据
export fnuction useSelector(selector){
const store = useContext(Context)
const {getState} = store
const selectedState = selector(getState())
return selectedState
}
export function useDispatch(){
const store = useStore()
return store.dispatch
}