開發與維運

升級antd 4.X

升級antd 4.X

1、andt 4.X
從 antd 3.x 版本升級到 antd 4.x 版本,參考antd官方升級指南[1]。先升級React,然後升級antd,升級命令和發生的錯誤時的解決方案如下文描述。
1.1. React 16.8升級至17.0.1
(1) 安裝React17.0.1:npm install [email protected] [email protected]
(2) 執行發生錯誤時:npm install @babel/runtime
1.2. antd 3.X 升級至4.8.4
 安裝指令
(1) 安裝antd: yarn add antd
(2) 兼容:npx -p @ant-design/codemod-v4 antd4-codemod src
 執行發生錯誤時
 執行發生錯誤時:npm install --save @ant-design/icons
 執行發生錯誤時:npm install --save @ant-design/compatible
 安裝:yarn add antd yarn add antd
 安裝:npm install --save react-resizable,後無法編譯通過時,重新安裝antd,yarn add antd
 執行發生錯誤時:npm start: Browserslist: caniuse-lite is outdated. Please run next command yarn upgrade: sudo npm i caniuse-lite browserslist,如錯誤,重新安裝antd
2、兼容3.X登錄頁
import React from 'react';
import { Form } from '@ant-design/compatible';
import { Input, Checkbox, Button } from 'antd';
import { withRouter } from 'react-router-dom';
import { inject, observer } from 'mobx-react';
@withRouter
@inject('HomeStore')
@observer
class LoginPage extends React.Component {
render() {

const { getFieldDecorator } = this.props.form;
return
      <Form onSubmit={this.handleSubmit} className="login-form2">
        <Form.Item>
          {getFieldDecorator('username', {
            rules: [{ required: true, message: '請輸入您的用戶名!' }],
          })(
            <Input
              size="large"
              prefix={<i className='iconfont iconuser' style={{ color: '#9D9D9D',marginRight:18,width:24,height:24 }} ></i>}
              placeholder="用戶名"
              style={{ maxWidth: 290,height:50 }}
            />,
          )}
        </Form.Item>

        <Form.Item>
          {getFieldDecorator('password', {
            rules: [{ required: true, message: '請輸入您的密碼!' }],
          })(
            <Input
              size="large"
              prefix={<i className='iconfont iconpassword' style={{ color: '#9D9D9D',marginRight:18 }}></i>}
              type="password"
              placeholder="密碼"
              style={{ maxWidth: 290,height:50 }}
            />,
          )}
        </Form.Item>

        <Form.Item>
          {getFieldDecorator('remember', {
            valuePropName: 'checked',
            initialValue: true,
          })(<Checkbox>記住密碼</Checkbox>)}
          <div className='login-btn2'>
            <Button type="primary" style={{ maxWidth: 290,padding:'8px 0', marginTop: 30,fontSize:16 }} htmlType="submit" className="login-form-button2">
              登錄
            </Button>
          </div>
        </Form.Item>
      </Form>

}

handleSubmit = e => {

e.preventDefault();
this.props.form.validateFields((err, values) => {
  if (!err) {
    if (values.remember) {
      for (let name in values) {
        setCookie(name, values[name]);
      }
    } 
    else {
      for (let name in values) {
        clearCookie(name);
      }
    }

    // 請求登陸接口
    this.props.HomeStore.setLogin({
      username: values.username,
      password: values.password
    }, (result) => {
      const { success, token, accessToken, refreshToken, tenantId } = result;
      if (success) {
        sessionStorage.setItem('selfToken', token);
        sessionStorage.setItem('accessToken', accessToken);
        sessionStorage.setItem('refreshToken', refreshToken);
        sessionStorage.setItem('tenantId', tenantId);
        sessionStorage.setItem('username', values.username); 

        this.props.history.push({
          pathname: '/',
          state: { username: values.username, password: values.password, selfToken: token }
        });
      }
    })
    
  }
});

};

//
componentDidMount() {

this.props.form.setFieldsValue({ 'username': getCookie('username') || '' });
this.props.form.setFieldsValue({ 'password': getCookie('password') || '' });
this.props.form.setFieldsValue({ 'remember': getCookie('remember') || '' });

}

}
const WrappedLoginForm = Form.create({ name: 'login' })(LoginPage);
export default WrappedLoginForm;

3、類組件(Class component)登錄頁
import React from 'react';
import '@ant-design/compatible/assets/index.css';
import { Form, Input, Checkbox, Button } from 'antd';
import { withRouter } from 'react-router-dom';
import { inject, observer } from 'mobx-react';

@withRouter
@inject('HomeStore')
@observer
class LoginPage extends React.Component {
formRef = React.createRef();
render() {

return 
      <Form name="basic"
            className="login-form2"
            onFinish={this.onFinish}
            onFinishFailed={this.onFinishFailed}
            ref={this.formRef}
      >  
        <Form.Item
          name="username"
          rules={[
            {
              required: true, 
              message: '請輸入您的用戶名!' 
            },
          ]}
        >
          <Input
            size="large"
            prefix={<i className='iconfont iconuser' style={{ color: '#9D9D9D',marginRight:18,width:24,height:24 }} ></i>}
            placeholder="用戶名1"
            style={{ maxWidth: 290,height:50 }}
          />
        </Form.Item>

        <Form.Item
          name="password"
          rules={[
            {
              required: true, 
              message: '請輸入您的密碼!' 
            },
          ]}
        >
            <Input
              size="large"
              prefix={<i className='iconfont iconpassword' style={{ color: '#9D9D9D',marginRight:18 }}></i>}
              type="password"
              placeholder="密碼"
              style={{ maxWidth: 290,height:50 }}
            />
        </Form.Item>

        <Form.Item name="remember" valuePropName="checked" initialValue="true">
          <Checkbox>記住密碼</Checkbox>
        </Form.Item>

        <Form.Item>
          <div className='login-btn2'>
            <Button type="primary" 
                    style={{ maxWidth: 290,padding:'8px 0', marginTop: 30,fontSize:16 }} 
                    htmlType="submit" 
                    className="login-form-button2">
              登錄
            </Button>
          </div>
        </Form.Item>
      </Form>

}

onFinish = (values) => {

console.log('Success:', values);

if (values.remember) {
  for (let name in values) {
    setCookie(name, values[name]);
  }
} 
else {
  for (let name in values) {
    clearCookie(name);
  }
}

// 請求登陸接口
this.props.HomeStore.setLogin({
  username: values.username,
  password: values.password
}, (result) => {
  const { success, token, accessToken, refreshToken, tenantId } = result;
  if (success) {
    sessionStorage.setItem('selfToken', token); 
    sessionStorage.setItem('accessToken', accessToken);
    sessionStorage.setItem('refreshToken', refreshToken);
    sessionStorage.setItem('tenantId', tenantId);
    sessionStorage.setItem('username', values.username); 
    this.props.history.push({
      pathname: '/',
      state: { username: values.username, password: values.password, selfToken: token }
    });
  }
})

};

onFinishFailed = (errorInfo) => {

console.log('Failed:', errorInfo);

};

componentDidMount() {

this.formRef.current.setFieldsValue({ 'username': getCookie('username') || '' });
this.formRef.current.setFieldsValue({ 'password': getCookie('password') || '' });
this.formRef.current.setFieldsValue({ 'remember': getCookie('remember') || '' });

}

}

export default LoginPage;

4、函數組件(Function component)登錄頁
import React, { useState, useEffect } from 'react';
import { Form, Input, Checkbox, Button } from 'antd';
import { withRouter } from 'react-router-dom';
import { inject, observer } from 'mobx-react';

const LoginPage = (props) => {
const [form] = Form.useForm();

useEffect(()=>{

console.log("僅僅一次執行:相當於componentDidMount");

form.setFieldsValue({ 'username': getCookie('username') || '' });
form.setFieldsValue({ 'password': getCookie('password') || '' });
form.setFieldsValue({ 'remember': getCookie('remember') || '' });

},[]);

const onFinish = (values) => {

console.log('Success:', values);

if (values.remember) {
  for (let name in values) {
    setCookie(name, values[name]);
  }
} 
else {
  for (let name in values) {
    clearCookie(name);
  }
}

props.HomeStore.setLogin({
  username: values.username,
  password: values.password
}, (result) => {
  const { success, token, accessToken, refreshToken, tenantId } = result;
  if (success) {
    sessionStorage.setItem('selfToken', token); 
    sessionStorage.setItem('accessToken', accessToken);
    sessionStorage.setItem('refreshToken', refreshToken);
    sessionStorage.setItem('tenantId', tenantId);
    sessionStorage.setItem('username', values.username); 
    props.history.push({
      pathname: '/',
      state: { username: values.username, password: values.password, selfToken: token }
    });
  }
})

};

const onFinishFailed = (errorInfo) => {

console.log('Failed:', errorInfo);

};

return (

    <Form name="basic"
          className="login-form2"
          onFinish={onFinish}
          onFinishFailed={onFinishFailed}
          form={form}
    >  
      <Form.Item
        name="username"
        rules={[
          {
            required: true, 
            message: '請輸入您的用戶名!' 
          },
        ]}
      >
        <Input
          size="large"
          prefix={<i className='iconfont iconuser' style={{ color: '#9D9D9D',marginRight:18,width:24,height:24 }} ></i>}
          placeholder="用戶名1"
          style={{ maxWidth: 290,height:50 }}
        />
      </Form.Item>

      <Form.Item
        name="password"
        rules={[
          {
            required: true, 
            message: '請輸入您的密碼!' 
          },
        ]}
      >
          <Input
            size="large"
            prefix={<i className='iconfont iconpassword' style={{ color: '#9D9D9D',marginRight:18 }}></i>}
            type="password"
            placeholder="密碼"
            style={{ maxWidth: 290,height:50 }}
          />
      </Form.Item>

      <Form.Item name="remember" valuePropName="checked" initialValue="true">
        <Checkbox>記住密碼</Checkbox>
      </Form.Item>

      <Form.Item>
        <div className='login-btn2'>
          <Button type="primary" 
                  style={{ maxWidth: 290,padding:'8px 0', marginTop: 30,fontSize:16 }} 
                  htmlType="submit" 
                  className="login-form-button2">
            登錄
          </Button>
        </div>
      </Form.Item>
    </Form>

);
}

export default inject('HomeStore')(observer(withRouter(LoginPage)));

參考文獻:
[1] 從 v3 到 v4,https://ant.design/docs/react/migration-v4-cn

Leave a Reply

Your email address will not be published. Required fields are marked *