Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

记第一次写react+ts遇到的坑 #8

Open
lovelmh13 opened this issue Nov 24, 2019 · 2 comments
Open

记第一次写react+ts遇到的坑 #8

lovelmh13 opened this issue Nov 24, 2019 · 2 comments

Comments

@lovelmh13
Copy link
Owner

lovelmh13 commented Nov 24, 2019

边学react和ts边记录一下最近一阵遇到的坑

在tsx中使用antd-mobile的受控InputItem

受控InputItem,需要用到rc-form,把官网的例子直接复制过来会报各种错误,对于刚学习tsreact的我来说,着实有些懵,后来通过修改,发现主要问题出现在ts的类型声明和接口上。

还需要注意的是,this.props.formgetFieldPropsvalidateFields等方法通过createForm<any>()(Entry);挂在到Entry上的,所以这句话一定要写。

于是改写为:

import React from 'react';
import { List, InputItem, Button, WingBlank, WhiteSpace } from 'antd-mobile';
import { createForm } from 'rc-form';
import './entry.scss';

interface Props {
	form: any;
}
interface State {
	msg: string;
}

class Entry extends React.Component<Props, State> {
	// 登陆
	signIn = () => {
		this.props.form.validateFields({ force: true }, (error: any) => {
			// 通过验证
			if (!error) {
				console.log(this.props.form.getFieldsValue());
			} else {
				alert(error.account.errors[0].message); // error需要可以.出来属性,声明的时候不要写error:object,而要写any
			}
		});
	};

	// 注册
	signUp = () => {
		alert('注册');
	};

	validateAccount = (rule: object, value: string, callback: (param1?: object) => void) => {
		if (value && value.length > 4) {
			callback();
		} else {
			callback(new Error('至少四个字符的帐户'));
		}
	};

	render() {
		const { getFieldProps } = this.props.form;
		return (
			<div className='main'>
				<div className='placeholder'></div>

				<header className='head'>
					<h1 className='title'>CodeReveiew</h1>
					<h1 className='title'>&</h1>
					<h1 className='title'>技术分享</h1>
					<h4 className='title'>记录你的技术储备</h4>
				</header>

				<div className='placeholder'></div>

				<WingBlank>
					<List className='entry'>
						<InputItem
							{...getFieldProps('account', {
								rules: [
									{
										required: true,
										message: '请填写账户'
									},
									{ validator: this.validateAccount }
								]
							})}
							className='inputItem'
							placeholder='please input account'>
							账号
						</InputItem>
						<WhiteSpace size='lg' className='whiteSpace' />
						<InputItem
							className='inputItem'
							placeholder='please input password'
							type='password'>
							密码
						</InputItem>
					</List>
					<WhiteSpace size='lg' className='whiteSpace' />
					<div className='buttonGroup'>
						<Button type='primary' inline onClick={this.signIn}>
							登陆
						</Button>
						<Button type='ghost' inline onClick={this.signUp}>
							注册
						</Button>
					</div>
				</WingBlank>
			</div>
		);
	}
}

const View: any = createForm<any>()(Entry); // 这里会将form挂在到props上,并带有getFieldProps等方法
export { View };

ts中需要对一个对象进行.操作

在上面的代码中,有这么一段:

signIn = () => {
		this.props.form.validateFields({ force: true }, (error: any) => {
			// 通过验证
			if (!error) {
				console.log(this.props.form.getFieldsValue());
			} else {
				alert(error.account.errors[0].message); 
			}
		});
	};

可以看见在else中,需要error.account这个操作。

开始我是error: object来声明的,但是会报错:类型“object”上不存在属性“account”。,这时只需要改为error: any就可以进行.操作了

在ts中引用rc-form

找不到@types/rc-form,于是在网上找了一个解决方法:

node_modules -> rc-form -> lib ,创建一个index.d.ts,写入以下内容:

import { Component, ClassicComponentClass, ClassType, ComponentClass, ComponentSpec, Mixin, ReactNode, ClassicComponent, ComponentState } from "react";
import PropTypes, { Requireable, InferProps } from "prop-types";
 
export interface ValidateMessages {
  'default'?: string;
  required?: string;
  'enum'?: string;
  whitespace?: string;
  date?: {
    format?: string;
    parse?: string;
    invalid?: string;
  };
  types?: {
    string?: string;
    method?: string;
    array?: string;
    object?: string;
    number?: string;
    date?: string;
    boolean?: string;
    integer?: string;
    float?: string;
    regexp?: string;
    email?: string;
    url?: string;
    hex?: string;
  };
  string?: {
    len?: string;
    min?: string;
    max?: string;
    range?: string;
  };
  number?: {
    len?: string;
    min?: string;
    max?: string;
    range?: string;
  };
  array?: {
    len?: string;
    min?: string;
    max?: string;
    range?: string;
  };
  pattern?: {
    mismatch?: string;
  };
  clone?: () => ValidateMessages;
}
export class Field { [s: string]: any }
 
export type FormTrigger = 'onChange' | 'onBlur' | 'onMouseOver' | 'onMouseMove' | 'onMouseOut' |
  'onEnter' | 'onLeave';
export type FormValidateType = 'string' | 'number' | 'boolean' | 'method' | 'regexp' | 'integer' |
  'float' | 'array' | 'object' | 'enum' | 'date' | 'url' | 'hex' | 'email';
export interface FormValidateRule {
  type?: FormValidateType;
  required?: boolean;
  message?: any;
  pattern?: RegExp;
  range?: { min?: number; max?: number };
  len?: number;
  role?: { type: "enum", enum: any[] };
  fields?: {
    [fieldName: string]: FormValidateRule;
    [fieldIndex: number]: FormValidateRule;
  };
  defaultField?: FormValidateRule;
  transform?: (value: any) => any;
  asyncValidator?(rule: FormValidateRule, value: any): Promise<any>;
  asyncValidator?(rule: FormValidateRule, value: any, callback: (error?: any) => void): void;
  validator?(
    rule: FormValidateRule,
    value: any,
    callback?: (error?: Error) => void,
    source?: ValidateValues,
    options?: ValidateFieldsOptions
  ): boolean | Error | Error[];
  [ruleName: string]: any;
}
 
export interface GetFieldPropsOptions {
  valuePropName?: string;
  getValueProps?(value: any): any;
  getValueFromEvent?(e: any): any;
  initialValue?: any;
  normalize?(value: any, prev: any, all: any): any;
  trigger?: FormTrigger;
  validateTrigger?: FormTrigger;
  rules?: FormValidateRule | FormValidateRule[];
  validateFirst?: boolean;
  validate?: { trigger?: FormTrigger; rules?: FormValidateRule | FormValidateRule[] };
  hidden?: boolean;
  preserve?: boolean;
}
 
export type ValidateErrors = {
  [fieldName: string]: {
    errors: Array<{ message: string; field: string; [s: string]: any }>
  }
} | null;
export type ValidateValues = {
  [fieldName: string]: any
};
export type ValidateFieldsOptions = {
  suppressWarning?: boolean;
  first: boolean;
  firstFields?: boolean | string[];
  force?: boolean;
  messages?: ValidateMessages;
  [s: string]: any;
};
 
export interface WrappedFormMethods {
  getFieldProps(name: string, options: GetFieldPropsOptions): any;
  getFieldDecorator(name: string, option: any): (node: ReactNode) => ReactNode;
  getFieldsValue(fieldName?: string[]): any;
  getFieldValue(fieldName: string): any;
  getFieldInstance(fieldName: string): any;
  setFieldsValue(changedValues: any, callback: (...args: any[]) => any): void;
  setFields(maybeNestedFields: any, callback: (...args: any[]) => any): void;
  setFieldsInitialValue(initialValues: any): void;
 
  validateFields(fieldNames: string[], options: ValidateFieldsOptions, callback: (errors: ValidateErrors, values: any[]) => void): Promise<any>;
  validateFields(fieldNames: string[], options: ValidateFieldsOptions): Promise<any>;
  validateFields(options: ValidateFieldsOptions, callback: (errors: ValidateErrors, values: any[]) => void): Promise<any>;
  validateFields(fieldNames: string[], callback: (errors: ValidateErrors, values: any[]) => void): Promise<any>;
  validateFields(callback: (errors: ValidateErrors, values: any[]) => void): Promise<any>;
 
  getFieldsError(names?: string[]): any;
  getFieldError(name: string): any;
  isFieldValidating(name: string): boolean;
  isFieldsValidating(names?: string[]): boolean;
  isFieldTouched(name: string): boolean;
  isFieldsTouched(names?: string[]): boolean;
  isSubmitting(): boolean; // Deprecated
  submit(callback: (setSubmitting: () => void) => void): void // Deprecated
  resetFields(names?: string[]): void;
}
 
type Shaped<P> = {
  [K in keyof P]: PropTypes.Requireable<(...args: any[]) => any>;
}
 
export interface FormMixin<P, S> extends Array<Mixin<P, S>> {
  getForm(): WrappedFormMethods;
}
 
export type WrappedFormClass<P> = ComponentClass<P> & WrappedFormMethods;
 
export type Decorate<P> = (WrappedComponent: ComponentClass<P>) => WrappedFormClass<P>;
 
 
export type FormPropsType<F> = { [K in keyof F]: WrappedFormMethods; };
export type PropsWithForm<P, F> = P & FormPropsType<F>;
 
export interface CreateFormOptions<P> {
  validateMessages?: ValidateMessages;
  onFieldsChange?: (props: P, changed: any, all: any) => void;
  onValuesChange?: (props: P, changed: any, all: any) => void;
  mapProps?: (props: P) => P;
  mapPropsToFields?: (props: P) => void;
  fieldNameProp?: string;
  fieldMetaProp?: string;
  fieldDataProp?: string;
  formPropName?: string;
  name?: string;
  withRef?: boolean; // deprecated
}
 
export function createForm<P>(options?: CreateFormOptions<P>): Decorate<P>;
export function createFormField(field: any): Field;
export const formShape: Requireable<InferProps<Shaped<WrappedFormMethods>>>;
  
 
declare module 'rc-form';
@ixugo
Copy link

ixugo commented Nov 11, 2020

解决了 , 感谢 Thanks♪(・ω・)ノ

@lovelmh13
Copy link
Owner Author

lovelmh13 commented Nov 15, 2020

解决了 , 感谢 Thanks♪(・ω・)ノ

wow , 本来是记录给自己看的,没想到还帮助到了别人~ 看来我还要继续记录下去呀 谢谢你~

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants