全站限时优惠至少 8 折起

剧场模式
首页前后端分离Ant DesignUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程

UmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #30 注册页面成功跳转

求知小风 · 真仙发布于新课程
0

https://ant.design/components/button-cn/

new.tsx

import { Form, Input, Row, Col, Button, message } from 'antd';

import React from 'react';
import styles from './style.less';
import { FormComponentProps } from 'antd/es/form';
import { Dispatch } from 'redux';
import { StateType } from './model';
import { connect } from 'dva';
import router from 'umi/router';

interface RegisterProps extends FormComponentProps {
  dispatch: Dispatch<any>;
  userRegister: StateType;
  submitting: boolean;
}

interface RegisterState {
  count: number;
  disabled: boolean;
}

export interface UserRegisterParams {
  user: {
    email: string;
    username: string;
    password: string;
    password_confirmation: string;
    phone: string;
    code: string;
  };
}

export interface CaptchaParams {
  mobile: string;
}

@connect(
  ({
    userRegister,
    loading,
  }: {
    userRegister: StateType;
    loading: {
      effects: {
        [key: string]: string;
      };
    };
  }) => ({
    userRegister,
    submitting: loading.effects['userRegister/submit'],
  }),
)
class RegistrationForm extends React.Component<RegisterProps, RegisterState> {
  state: RegisterState = {
    count: 0,
    disabled: false,
  };

  componentDidUpdate() {
    const { userRegister } = this.props;

    if (userRegister.success) {
      message.success('注册成功!');
      router.push({
        pathname: '/',
        state: {},
      });
    }
  }

  handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    const { dispatch, form } = this.props;
    form.validateFieldsAndScroll((err, values) => {
      dispatch({
        type: 'userRegister/submit',
        payload: { ...values },
      });
    });
  };

  interval: number | undefined = undefined;

  onGetCaptcha = () => {
    const { form, dispatch } = this.props;
    const phone = form.getFieldValue('user[phone]');

    if (phone === undefined || phone.trim() === '') {
      message.error('请输入手机号码');
      return;
    }

    let count = 59;
    this.setState({
      count,
      disabled: true,
    });
    this.interval = window.setInterval(() => {
      count -= 1;
      this.setState({
        count,
      });

      if (count === 0) {
        clearInterval(this.interval);
        this.setState({
          disabled: false,
        });
      }
    }, 1000);

    dispatch({
      type: 'userRegister/getCaptcha',
      payload: { mobile: phone },
    });
  };

  onGetCaptchaImage = () => {
    // const randomString =
    //   Math.random()
    //     .toString(36)
    //     .substring(2, 15) +
    //   Math.random()
    //     .toString(36)
    //     .substring(2, 15);
    // const randomString = uuidv4();
    // this.setState({
    //   image: `http://localhost:5000/rucaptcha?a=${randomString}`,
    // });

    const { dispatch } = this.props;

    dispatch({
      type: 'userRegister/onGetCaptchaImage',
    });
  };

  render() {
    const { submitting, userRegister } = this.props;
    const { getFieldDecorator } = this.props.form;
    const { errors, image } = userRegister;

    const { count, disabled } = this.state;

    const formItemLayout = {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 8 },
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 },
      },
    };
    const tailFormItemLayout = {
      wrapperCol: {
        xs: {
          span: 24,
          offset: 0,
        },
        sm: {
          span: 16,
          offset: 8,
        },
      },
    };

    return (
      <div className={styles.custom_form}>
        <Form {...formItemLayout} onSubmit={this.handleSubmit}>
          <Form.Item
            validateStatus={errors.username ? 'error' : ''}
            help={errors.username ? errors.username.join(', ') : ''}
            label={<span>Username&nbsp;</span>}
          >
            {getFieldDecorator('user[username]')(<Input />)}
          </Form.Item>
          <Form.Item
            validateStatus={errors.email ? 'error' : ''}
            help={errors.email ? errors.email.join(', ') : ''}
            label="E-mail"
          >
            {getFieldDecorator('user[email]')(<Input type="email" />)}
          </Form.Item>
          <Form.Item
            validateStatus={errors.password ? 'error' : ''}
            help={errors.password ? errors.password.join(', ') : ''}
            label="Password"
            hasFeedback
          >
            {getFieldDecorator('user[password]')(<Input.Password />)}
          </Form.Item>
          <Form.Item
            validateStatus={errors.password_confirmation ? 'error' : ''}
            help={errors.password_confirmation ? errors.password_confirmation.join(', ') : ''}
            label="Confirm Password"
            hasFeedback
          >
            {getFieldDecorator('user[password_confirmation]')(<Input.Password />)}
          </Form.Item>

          <Form.Item
            validateStatus={errors.phone ? 'error' : ''}
            help={errors.phone ? errors.phone.join(', ') : ''}
            label="Phone Number"
          >
            {getFieldDecorator('user[phone]')(<Input style={{ width: '100%' }} />)}
          </Form.Item>
          <Form.Item
            validateStatus={errors.code ? 'error' : ''}
            help={errors.code ? errors.code.join(', ') : ''}
            label="Captcha"
            extra="We must make sure that your are a human."
          >
            <Row gutter={8}>
              <Col span={12}>{getFieldDecorator('user[code]')(<Input />)}</Col>
              <Col span={12}>
                <Button disabled={disabled} onClick={this.onGetCaptcha}>
                  {count ? `${count} s` : '获取验证码'}
                </Button>
              </Col>
            </Row>
          </Form.Item>
          <Form.Item
            validateStatus={errors.rucaptcha ? 'error' : ''}
            help={errors.rucaptcha ? errors.rucaptcha.join(', ') : ''}
            label="图形验证码"
          >
            <Row gutter={8}>
              <Col span={12}>{getFieldDecorator('_rucaptcha')(<Input />)}</Col>
              <Col span={12}>
                <img src={image} onClick={this.onGetCaptchaImage} />
              </Col>
            </Row>
          </Form.Item>
          <Form.Item {...tailFormItemLayout}>
            <Button loading={submitting} type="primary" htmlType="submit">
              Register
            </Button>
          </Form.Item>
        </Form>
      </div>
    );
  }
}

export default Form.create<RegisterProps>({ name: 'register' })(RegistrationForm);

model.ts

import { AnyAction, Reducer } from 'redux';

import { EffectsCommandMap } from 'dva';
import { fakeRegister, fakeCaptcha } from './service';
import uuidv4 from 'uuid/v4';

export interface StateType {
  success?: boolean;
  currentAuthority?: 'user' | 'guest' | 'admin';
  errors?: any;
  image?: string;
  response?: any;
}

export type Effect = (
  action: AnyAction,
  effects: EffectsCommandMap & { select: <T>(func: (state: StateType) => T) => T },
) => void;

export interface ModelType {
  namespace: string;
  state: StateType;
  effects: {
    submit: Effect;
    getCaptcha: Effect;
    onGetCaptchaImage: Effect;
  };
  reducers: {
    registerHandle: Reducer<StateType>;
    errorsHandle: Reducer<StateType>;
    setCaptchaImage: Reducer<StateType>;
    clearErrors: Reducer<StateType>;
  };
}

const Model: ModelType = {
  namespace: 'userRegister',

  state: {
    success: false,
    errors: {},
    response: {},
    image: 'http://localhost:5000/rucaptcha',
  },

  effects: {
    *submit({ payload }, { call, put }) {
      try {
        const response = yield call(fakeRegister, payload);
        yield put({
          type: 'registerHandle',
          payload: response,
        });
        yield put({
          type: 'clearErrors',
        });
      } catch (e) {
        yield put({
          type: 'errorsHandle',
          payload: e.data.errors,
        });

        yield put({
          type: 'onGetCaptchaImage',
        });
      }
    },
    *onGetCaptchaImage({}, { put }) {
      yield put({
        type: 'setCaptchaImage',
      });
    },

    *getCaptcha({ payload }, { call }) {
      yield call(fakeCaptcha, payload);
    },
  },

  reducers: {
    registerHandle(state, { payload }) {
      return {
        ...state,
        success: payload.success,
        response: payload.response,
      };
    },
    errorsHandle(state, { payload }) {
      return {
        ...state,
        errors: payload,
      };
    },

    clearErrors(state, {}) {
      return {
        ...state,
        errors: {},
      };
    },

    setCaptchaImage(state, {}) {
      const randomString = uuidv4();
      return {
        ...state,
        image: `http://localhost:5000/rucaptcha?a=${randomString}`,
      };
    },
  },
};

export default Model;
0 条回复
暂无回复~~
加微信(qiuzhi99666)入群官方服务号
随机课程
React & Redux 实战 Reminder Pro 项目

React & Redux 实战 Reminder Pro 项目

5 个视频31 分钟初级

Pro¥ 59.00¥ 47.20

Redux已完结

课程目录

1FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #1 开始玩起来

2FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #2 了解项目源码并尝试修改

3FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #3 继续了解项目源码并修改代码

4FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #4 如何修改 footer 及其原理

5FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #5 关于 footer 和 layout

6ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #6 如何好好利用 ant-design-pro-layout

7ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #7 如何下载和使用区块

8ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #8 为什么下载区块后会添加菜单

9ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #9 umi-plugin-pro-block-ts

10ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #10 删除国际化 i18n part 1

11ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #11 删除国际化 i18n part 2

12ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #12 用户注册的 block

13ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #13 让用户注册工作起来

14ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #14 注册的流程理解

15ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #15 准备好 API

16ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #16 对接好后端的注册功能

17ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #17 表单的前端验证与后端验证

18ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #18 后端的数据验证与前端的结合

19ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #19 自己写一个真实项目的注册页面 - 手机验证码 - 图形验证码

20ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #20 注册表单

21ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #21 表单与 TypeScript

22ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #22 注册表单 - connect - dispatch

23ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #23 实现注册功能并显示验证出错信息

24ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #24 详解注册页面手机验证码

25ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #25 注册页面手机验证码处理完成

26ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #26 手机验证码的原理(后端)

27ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #27 注册页面显示图形验证码

28ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #28 注册页面图形验证码的原理

29ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #29 注册页面提交失败时图形验证码重新刷新

FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #30 注册页面成功跳转

31ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #31 用 localStorage 存储 jwt

32FreeUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #32 重构代码,封装 request

33ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #33 登录页面

34ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #34 完成登录

35ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #35 登录权限验证 - 发送请求带上头信息

36ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #36 登录权限验证 - umi-request 异常处理程序

37ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #37 解决 umi-request 的 extend 关于 headers 的问题

38ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #38 显示个人用户信息

39ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #39 菜单权限控制显示

40ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #40 通过修改 getAuthority 方法利用 jwt 显示正确的菜单权限

41ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #41 刷新当前权限

42ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #42 其他的权限方法 - 从远程服务器获取菜单

43ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #43 权限验证的安全性(准备进入下一阶段)

44ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #44 实战 - 视频管理

45ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #45 实战 - 视频管理 - 视频列表

46ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #46 实战 - 视频管理 - 视频列表 - 发送请求获得远程的数据

47ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #47 实战 - 视频管理 - 视频列表 - 显示列表数据

48ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #48 实战 - 视频管理 - 视频列表 - 修复列表数据

49ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #49 实战 - 视频管理 - 视频列表 - 搜索列表

50ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #50 实战 - 视频管理 - 搜索 - 使用 qs 处理 umi-request 提交参数的问题

51ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #51 实战 - 视频管理 - 搜索 - 处理 moment 的时间问题

52ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #52 实战 - 视频管理 - 完成分页

53ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #53 实战 - 视频管理 - 添加视频

54ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #54 实战 - 视频管理 - 添加视频 - 发送请求

55ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #55 实战 - 视频管理 - 添加视频 - 处理完成

56ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #56 实战 - 视频管理 - 错误处理

57ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #57 实战 - 视频管理 - 详情页面

58ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #58 实战 - 视频管理 - 完成详情页面

59ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #59 实战 - 视频管理 - 删除视频

60ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #60 实战 - 视频管理 - 添加视频

61ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #61 实战 - 视频管理 - 添加视频 part 2

62ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #62 实战 - 视频管理 - 添加视频 part 3

63ProUmiJS & TypeScript & Ant Design Pro v4 从零开始实战教程 #63 完结

学员(120)
szheng3 · 大乘Yoko · 元婴钮乾坤 · 大乘乙💯 · 元婴KniGht · 元婴Mars.Liang · 道祖lchengcan · 道祖Gump · 元婴米斯特张 · 真仙向上人生 · 元婴geralt · 大乘答案 · 真仙
最新动态
szheng3 · 大乘学习到了10:53
Yoko · 元婴学习到了3:04
钮乾坤 · 大乘学习到了11:08
乙💯 · 元婴学习到了7:00
KniGht · 元婴学习到了0:00
统计信息
    学员: 17230
    视频数量: 990
    帖子数量: 423

© 汕尾市求知科技有限公司 | 粤ICP备19038915号 | 关注我们 | 在线学员:138

Top