步骤六:context用例【React项目创建】

228 阅读1分钟

何时使用

何时使用context是在做这个事情之前需要考虑的

全局状态变量,如用户信息UI主题这种整个项目组件之间共享的值。也可能是全局可获取的方法,比如用户登录退出登录等函数方法

如何使用

Context提供了Provider和Consumer两个组件,消费方式也有多种,主要从官网查看,因为项目中往往存在多个Context,所以项目中使用的是Consumer回调函数

配置

// user.tsx
import React from 'react';
import { UserInfo } from '@/models/user';

/** 默认值 */
const defaultValue = {
    /** 用户信息 */
    user: undefined as (undefined | UserInfo),
    /** 登录 */
    async login(username: string, password: string) {},
    /** 退出登录 */
    async logout() {},
    /** 是否登录 */
    isLogin: false,
};

export const UserContext = React.createContext(defaultValue);
export type UserState = typeof defaultValue;

/**
 * @description 用户状态
 * @author max
 * @date 2022/04/15
 * @export
 * @class UserProvider
 * @extends {React.PureComponent<{}, UserState>}
 */
export default class UserProvider extends React.PureComponent<{}, UserState> {
    constructor(props: {}) {
        super(props);
        this.state = {
            ...defaultValue, ...{
                login: this.login,
                logout: this.logout,
            },
        };
    }

    /** 登录 */
    login = async () => {
        console.info('login function');
        this.setState({isLogin: true});
        await new Promise((r) => r({}));
    };

    /** 退出登录 */
    logout = async () => {
        console.info('logout function');
        this.setState({
            isLogin: false,
        });
    };

    render() {
        const { children } = this.props;
        return (
            <UserContext.Provider value={this.state}>
                {children}
            </UserContext.Provider>
        );
    }
}

Provider

// index.tsx
import UserProvider from '@contexts/user';
ReactDOM.render(
    <UserProvider>
        <App />
    </UserProvider>
    document.getElementById('root'),
);

Consumer

当使用Context时间,往往不会只有一个,如果一个组件涉及到多个Context消费,就会出现“回调地狱”的情况,所以考虑使用高阶组件的方式进行一层包裹。写一个高阶函数

export function withContext<S>(Context: React.Context<S>) {
    return function <P extends S>(Component: React.ComponentType<P>) {
        return function(props: Omit<P, keyof S>) {
            return <Context.Consumer>{(data: S) => <Component {...{ ...props as any, ...data as any }} />}</Context.Consumer>;
        };
    };
}

如上,消费Context时,使用下面的方式就可以了

import { withContext } from '@contexts/index';
import { UserContext, UserState } from '@contexts/user';

export default withContext(UserContext)(Demo);

Demo组件就可以访问user这个context提供的数据和函数了

传送门