痛点
- 从官网可以知道Context的使用规则
- 项目中通过Context使用全局变量,为了功能单一原则,如
用户登录信息状态、加载状态、或者其他的全局变量,通过Provider提供 - 通过Context.Consumer进行消费,使用规则如下
<MyContext.Consumer>
{data => /** 基于context进行渲染 */}
</MyContext.Consumer>
- 从上面就会发现问题:如果有多个context,会出现
死亡回调,非常不雅观。如何处理这样的函数是需要解决的问题
解决方案
前期调研
- 使用高阶组件的方式,通过高阶组件接收Context、Component。返回一个函数组件FC,实现包装
怎么做
- 函数定义
function withContext<S extends any>(Context: React.Context<S>) { // 第一个参数是Context
return function<P extends S>(Component: React.ComponentType<P>) { // 第二个参数Component
return function(props: Omit<P, keyof S>) {
return (
<Context.Consumer>
{(data: S) =><Component {...{ ...props as any, ...data as any}} />}
</Context.Consumer>
)
}
}
}
- 定义context
// user.tsx
const defaultValue = { isLogin: false, logout(): void };
export const UserContext = React.createContext(defaultValue)
export type UserStata = typeof defaultValue;
export class UserProvider extends React.Component<{}, UserState> {
state = {
...defaultValue,
...{
logout:this.logout
}
}
logout = () => {
this.setState({
isLogin: true,
});
}
render() {
return (
<UserContext.Provider value={this.state}>
{this.props.children}
</UserContext.Provider>
)
}
}
- 提供全局变量
import { UserProvider } from "user.tsx";
ReactDOM.render(
<UserProvider>
<Login />
</UserProvider>
)
- 消费
// login.tsx
withContext(UserContext)(Login)
其他
注意React.Context<T>、React.ComponentType<T>的使用