React Hooks 间隔正式宣布已过去好几个月了,redux,mobx,也都支撑了 Hooks 的用法,那末有无可能用 React Context API & Hooks 来完成一个同时支撑 class component 和 functional component 接见的 store 呢?答案是一定的。
既然我们是基于 Context Api,那末先来建立一个 context 对象
// store.js
import React from 'react'
const initialStore = {}
const StoreContext = React.createContext(initialStore)
接着我们来组织两种接见 store 的要领:
Hooks 的体式格局:
// store.js
import {useReducer, useContext} from 'react'
// 声明 reducer
export const reducer = (state, action) => {
switch (action.type) {
case 'set':
return { ...state, ...action.payload }
case 'reset':
return {}
default:
throw new Error(
`action: '${action.type}' not defined`
)
}
}
// 基于原生 Hooks 完成
export const useStore = () => {
return useReducer(reducer, useContext(StoreContext))
}
HOC 的体式格局:
HOC 须要有一个上下文环境才能够接见 store,所以我们先来组织 provider
// 组织一个根组件 Provider
export const StoreProvider = ({ children }) => {
const [context, dispatch] = useStore()
return <StoreContext.Provider value={{ ...context, dispatch }}>{children}</StoreContext.Provider>
}
这个 StoreProvider 能够像 react-redux 的 Provider 一样,包裹在根组件的最外层
然后来看 consumer
export const connect = (WrappedComponent) => {
return class ConnectClass extends React.Component {
render () {
return (
<StoreContext.Consumer>
{
state => <WrappedComponent {...state} {...this.props} />
}
</StoreContext.Consumer>
)
}
}
}
我们封装了一个 connect 函数,作为 HOC,用法和 react-redux的 connect 的单参情势形似。
那末我们在组件内应当怎样运用呢?
Class Component
import React from 'react'
import { connect } from 'store'
export default @connect class Component extends React.Component {
handleClick = () => {
this.props.dispatch({type: 'set', payload: {a: 1}})
}
render() {
return (<div>
<div onClick={this.handleClick}>{JSON.stringify(this.props)}</div>
<div>{JSON.stringify(this.props)}</div>
</div>)
}
}
Functional Component
import React from 'react'
import { useStore } from 'store'
export default const Component = () => {
const [store, dispatch] = useStore()
const handleClick = () => {
dispatch({type: 'set', payload: {a: 1}})
}
return (<div>
<div>{JSON.stringify(store)}</div>
<div onClick={handleClick}>{JSON.stringify(store)}</div>
</div>)
}
至此,我们就完成了基于 react 原生 api 的跨组件通讯,hooks 和 hoc 的接见都经由过程 context api 完成,默许支撑了浅比较。