React useContext + useReducer 实现 Hooks 状态管理功能

App.tsx

import { useReducer } from 'react';
import { BrowserRouter, Switch } from 'react-router-dom';
import { renderRoutes } from 'react-router-config';
import routes from './router';
import { UserContext } from '@/store/user';
import { IUser, IReducerAction } from '@/common/types/interface';
import { UserStoreActionType } from '@/common/types/enum';

function App() {
  const myUserReducer = (state: IUser, action: IReducerAction): IUser => {
    const { type } = action;
    switch (type) {
      case UserStoreActionType.SetData:
        localStorage.setItem('userInfo', JSON.stringify({ ...state, ...action.params }));
        return { ...state, ...action.params };
      default:
        return state;
    }
  };
  const userStorage = localStorage.getItem('userInfo') || '';
  const initialUserState = userStorage ? JSON.parse(userStorage) : null;
  const [store, dispatch] = useReducer(myUserReducer, initialUserState);
  return (
    <UserContext.Provider value={{ store, dispatch }}>
      <BrowserRouter>
        <Switch>{renderRoutes(routes)}</Switch>
      </BrowserRouter>
    </UserContext.Provider>
  );
}
export default App;

创建 createContext (@/store/user)

import { createContext } from 'react';
import { IUser, IReducerAction } from '@/common/types/interface';
// import { UserStoreActionType } from '@/common/types/enum';

interface ICreateContext {
  store: IUser;
  dispatch: (params: IReducerAction) => void;
}
export const UserContext = createContext<ICreateContext>({
  store: {
    userName: '',
    sex: '',
    age: '',
    mobile: '',
    mailbox: '',
    password: ''
  },
  dispatch: () => {},
});

在登录时获取接口返回的数据,并更新到  store 中

import React, { useContext, useEffect } from 'react';
import { useHistory } from 'react-router-dom';
import { LoginWrapper, LoginContainer } from './styled';
import { Form, Input, Button, message } from 'antd';
import { login } from '@/api/login';
import { UserContext } from '@/store/user';
import { UserStoreActionType } from '@/common/types/enum';
import { useRequest } from 'ahooks';
import { useForm } from 'antd/lib/form/Form';

interface ILogin {
  userName: string;
  password: string;
}

const Login: React.FC = () => {
  const history = useHistory();
  const { dispatch } = useContext(UserContext);
  const [form] = useForm<ILogin>();

  useEffect(() => {
    // 设置默认参数
    form.setFieldsValue({ userName: 'Fengchengzhi', password: '123456' });
  }, []);

  const { loading, run } = useRequest((formVal: ILogin) => login(formVal), {
    manual: true,
    onSuccess: (res) => {
      message.success((res as any).message);
      dispatch({
        type: UserStoreActionType.SetData,
        params: res.data,
      });
      setTimeout(() => {
        history.push('/home');
      }, 1000);
    }
  });

  const onFinish = (formData: ILogin) => {
    run(formData);
  };

  const onFinishFailed = () => {
    // throw new Error('请填写完整信息!');
  };

  // 注册
  const onRegister = () => {
    history.push('/register');
  };

  return (
    <LoginWrapper>
      <LoginContainer>
        <h2>登录</h2>
        <Form
          name="basic"
          labelCol={{ span: 6 }}
          wrapperCol={{ span: 18 }}
          form={form}
          onFinish={onFinish}
          onFinishFailed={onFinishFailed}
          autoComplete="off"
        >
          <Form.Item
            label="Username"
            name="userName"
            rules={[{ required: true, message: 'Please input your username!' }]}
          >
            <Input />
          </Form.Item>
          <Form.Item
            label="Password"
            name="password"
            rules={[{ required: true, message: 'Please input your password!' }]}
          >
            <Input.Password />
          </Form.Item>
          <Form.Item wrapperCol={{ offset: 10, span: 14 }}>
            <Button
              type="primary"
              loading={loading}
              htmlType="submit"
            >
              登录
            </Button>
          </Form.Item>
          <Form.Item wrapperCol={{ offset: 10, span: 14 }}>
            <Button type="link" onClick={onRegister}>
              注册
            </Button>
          </Form.Item>
        </Form>
      </LoginContainer>
    </LoginWrapper>
  );
};

export default Login;

UserStoreActionType 

export enum UserStoreActionType {
  SetData = 'SET_DATA',
}

获取 store 数据并展示

import React, { useContext } from "react";
import { HeaderWrapper } from './styled'
import { UserContext } from '../../store/user'

const HeaderComps: React.FC = () => {
  const { store: userInfo } = useContext(UserContext)
  return (
    <HeaderWrapper className="header-wrapper">
      用户姓名:{ userInfo.userName }
    </HeaderWrapper>
  )
}

export default HeaderComps

 

posted @ 2022-04-11 21:55  爱放屁的菜鸟  阅读(156)  评论(0编辑  收藏  举报