Skip to content

Commit e53a1f2

Browse files
authored
chore: finish all TODO (#12)
* remove todo * fix lint
1 parent f361156 commit e53a1f2

File tree

10 files changed

+87
-48
lines changed

10 files changed

+87
-48
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@ In `rc-form`, we support like `user.name` to be a name and convert value to `{ u
217217

218218
Field Form will only trade `['user', 'name']` to be `{ user: { name: 'Bamboo' } }`, and `user.name` to be `{ ['user.name']: 'Bamboo' }`.
219219

220+
## 🔥 Remove `validateFieldsAndScroll`
221+
222+
Since `findDomNode` is marked as warning in [StrictMode](https://reactjs.org/docs/strict-mode.html#warning-about-deprecated-finddomnode-usage). It seems over control of Form component.
223+
We decide to remove `validateFieldsAndScroll` method and you should handle it with you own logic:
224+
225+
```jsx
226+
<Form>
227+
<Field name="username">
228+
<input ref={this.inputRef} />
229+
</Field>
230+
</Form>
231+
```
232+
220233
## 🔥 `getFieldsError` always return array
221234

222235
`rc-form` returns `null` when no error happen. This makes user have to do some additional code like:

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"compile": "father build",
3333
"gh-pages": "rc-tools run gh-pages",
3434
"pub": "rc-tools run pub --babel-runtime",
35-
"lint": "eslint src/**/*",
35+
"lint": "eslint src/ --ext .tsx,.ts",
3636
"test": "father test",
3737
"now-build": "npm run build"
3838
},

src/Field.tsx

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import {
1212
ValidateOptions,
1313
InternalFormInstance,
1414
RuleObject,
15+
StoreValue,
16+
EventArgs,
1517
} from './interface';
1618
import FieldContext, { HOOK_MARK } from './FieldContext';
1719
import { toArray } from './utils/typeUtil';
@@ -25,10 +27,10 @@ import {
2527
} from './utils/valueUtil';
2628

2729
interface ChildProps {
28-
value?: any;
29-
onChange?: (...args: any[]) => void;
30-
onFocus?: (...args: any[]) => void;
31-
onBlur?: (...args: any[]) => void;
30+
value?: StoreValue;
31+
onChange?: (...args: EventArgs) => void;
32+
onFocus?: (...args: EventArgs) => void;
33+
onBlur?: (...args: EventArgs) => void;
3234
}
3335

3436
export interface FieldProps {
@@ -41,11 +43,11 @@ export interface FieldProps {
4143
* will trigger validate rules and render.
4244
*/
4345
dependencies?: NamePath[];
44-
getValueFromEvent?: (...args: any[]) => any;
46+
getValueFromEvent?: (...args: EventArgs) => StoreValue;
4547
name?: NamePath;
46-
normalize?: (value: any, prevValue: any, allValues: any) => any;
48+
normalize?: (value: StoreValue, prevValue: StoreValue, allValues: Store) => StoreValue;
4749
rules?: Rule[];
48-
shouldUpdate?: (prevValues: any, nextValues: any, info: { source?: string }) => boolean;
50+
shouldUpdate?: (prevValues: Store, nextValues: Store, info: { source?: string }) => boolean;
4951
trigger?: string;
5052
validateTrigger?: string | string[] | false;
5153
}
@@ -77,7 +79,7 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
7779
*/
7880
private touched: boolean = false;
7981

80-
private validatePromise: Promise<any> | null = null;
82+
private validatePromise: Promise<string[]> | null = null;
8183

8284
// We reuse the promise to check if is `validating`
8385
private prevErrors: string[];
@@ -149,7 +151,7 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
149151
// ========================= Field Entity Interfaces =========================
150152
// Trigger by store update. Check if need update the component
151153
public onStoreChange = (
152-
prevStore: any,
154+
prevStore: Store,
153155
namePathList: InternalNamePath[] | null,
154156
info: NotifyInfo,
155157
) => {
@@ -178,7 +180,7 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
178180
this.touched = data.touched;
179181
}
180182
if ('validating' in data) {
181-
this.validatePromise = data.validating ? Promise.resolve() : null;
183+
this.validatePromise = data.validating ? Promise.resolve([]) : null;
182184
}
183185

184186
this.refresh();
@@ -284,7 +286,7 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
284286
public getOnlyChild = (
285287
children:
286288
| React.ReactNode
287-
| ((control: ChildProps, meta: Meta, context: any) => React.ReactNode),
289+
| ((control: ChildProps, meta: Meta, context: FormInstance) => React.ReactNode),
288290
): { child: React.ReactElement | null; isFunction: boolean } => {
289291
// Support render props
290292
if (typeof children === 'function') {
@@ -315,10 +317,11 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
315317
public getControlled = (childProps: ChildProps = {}) => {
316318
const { trigger, validateTrigger, getValueFromEvent, normalize } = this.props;
317319
const namePath = this.getNamePath();
318-
const { getInternalHooks, validateFields, getFieldsValue }: InternalFormInstance = this.context;
320+
const { getInternalHooks, getFieldsValue }: InternalFormInstance = this.context;
319321
const { dispatch } = getInternalHooks(HOOK_MARK);
320322
const value = this.getValue();
321323

324+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
322325
const originTriggerFunc: any = childProps[trigger];
323326

324327
const control = {
@@ -327,7 +330,7 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
327330
};
328331

329332
// Add trigger
330-
control[trigger] = (...args: any[]) => {
333+
control[trigger] = (...args: EventArgs) => {
331334
// Mark as touched
332335
this.touched = true;
333336

@@ -354,7 +357,7 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
354357
validateTriggerList.forEach((triggerName: string) => {
355358
// Wrap additional function of component, so that we can get latest value from store
356359
const originTrigger = control[triggerName];
357-
control[triggerName] = (...args: any[]) => {
360+
control[triggerName] = (...args: EventArgs) => {
358361
if (originTrigger) {
359362
originTrigger(...args);
360363
}
@@ -364,8 +367,11 @@ class Field extends React.Component<FieldProps, FieldState> implements FieldEnti
364367
if (rules && rules.length) {
365368
// We dispatch validate to root,
366369
// since it will update related data with other field with same name
367-
// TODO: use dispatch instead
368-
validateFields([namePath], { triggerName });
370+
dispatch({
371+
type: 'validateField',
372+
namePath,
373+
triggerName,
374+
});
369375
}
370376
};
371377
});

src/FieldContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { InternalFormInstance } from './interface';
44

55
export const HOOK_MARK = 'RC_FORM_INTERNAL_HOOKS';
66

7+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
78
const warningFunc: any = () => {
89
warning(false, 'Can not find FormContext. Please make sure you wrap Field under Form.');
910
};

src/Form.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ import FormContext, { FormContextProps } from './FormContext';
1313

1414
type BaseFormProps = Omit<React.FormHTMLAttributes<HTMLFormElement>, 'onSubmit'>;
1515

16+
type RenderProps = (values: Store, form: FormInstance) => JSX.Element | React.ReactNode;
17+
1618
export interface FormProps extends BaseFormProps {
1719
initialValues?: Store;
1820
form?: FormInstance;
19-
children?: (() => JSX.Element | React.ReactNode) | React.ReactNode;
21+
children?: RenderProps | React.ReactNode;
2022
fields?: FieldData[];
2123
name?: string;
2224
validateMessages?: ValidateMessages;
@@ -90,7 +92,7 @@ const Form: React.FunctionComponent<FormProps> = (
9092
const childrenRenderProps = typeof children === 'function';
9193
if (childrenRenderProps) {
9294
const values = formInstance.getFieldsValue();
93-
childrenNode = (children as any)(values, formInstance);
95+
childrenNode = (children as RenderProps)(values, formInstance);
9496
}
9597

9698
// Not use subscribe when using render props

src/List.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import * as React from 'react';
22
import warning from 'warning';
3-
import { InternalNamePath, NamePath, InternalFormInstance } from './interface';
3+
import { InternalNamePath, NamePath, InternalFormInstance, StoreValue } from './interface';
44
import FieldContext, { HOOK_MARK } from './FieldContext';
55
import Field from './Field';
66
import { getNamePath, setValue } from './utils/valueUtil';
@@ -21,8 +21,8 @@ interface ListProps {
2121
}
2222

2323
interface ListRenderProps {
24-
value: any[];
25-
onChange: (value: any[]) => void;
24+
value: StoreValue[];
25+
onChange: (value: StoreValue[]) => void;
2626
}
2727

2828
const List: React.FunctionComponent<ListProps> = ({ name, children }) => {
@@ -38,7 +38,7 @@ const List: React.FunctionComponent<ListProps> = ({ name, children }) => {
3838
const parentPrefixName = getNamePath(context.prefixName) || [];
3939
const prefixName: InternalNamePath = [...parentPrefixName, ...getNamePath(name)];
4040

41-
const shouldUpdate = (prevValue: any, nextValue: any, { source }) => {
41+
const shouldUpdate = (prevValue: StoreValue, nextValue: StoreValue, { source }) => {
4242
if (source === 'internal') {
4343
return false;
4444
}

src/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ interface RefForm extends InternalForm {
1616
useForm: typeof useForm;
1717
}
1818

19-
const RefForm: RefForm = InternalForm as any;
19+
const RefForm: RefForm = InternalForm as RefForm;
2020

2121
RefForm.FormProvider = FormProvider;
2222
RefForm.Field = Field;

src/interface.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface Meta {
2020
*/
2121
export interface FieldData extends Partial<Meta> {
2222
name: NamePath;
23-
value?: any;
23+
value?: StoreValue;
2424
}
2525

2626
export type RuleType =
@@ -40,21 +40,21 @@ export type RuleType =
4040

4141
type Validator = (
4242
rule: Rule,
43-
value: any,
43+
value: StoreValue,
4444
callback: (error?: string) => void,
4545
) => Promise<void> | void;
4646

4747
export type RuleRender = (form: FormInstance) => RuleObject;
4848

4949
interface BaseRule {
50-
enum?: any[];
50+
enum?: StoreValue[];
5151
len?: number;
5252
max?: number;
53-
message?: any;
53+
message?: string;
5454
min?: number;
5555
pattern?: RegExp;
5656
required?: boolean;
57-
transform?: (value: any) => any;
57+
transform?: (value: StoreValue) => StoreValue;
5858
type?: RuleType;
5959
validator?: Validator;
6060
whitespace?: boolean;
@@ -79,10 +79,10 @@ export interface ValidateErrorEntity {
7979
}
8080

8181
export interface FieldEntity {
82-
onStoreChange: (store: any, namePathList: InternalNamePath[] | null, info: NotifyInfo) => void;
82+
onStoreChange: (store: Store, namePathList: InternalNamePath[] | null, info: NotifyInfo) => void;
8383
isFieldTouched: () => boolean;
8484
isFieldValidating: () => boolean;
85-
validateRules: (options?: ValidateOptions) => Promise<any>;
85+
validateRules: (options?: ValidateOptions) => Promise<string[]>;
8686
getMeta: () => Meta;
8787
getNamePath: () => InternalNamePath;
8888
props: {
@@ -105,8 +105,8 @@ export interface ValidateOptions {
105105
export type InternalValidateFields = (
106106
nameList?: NamePath[],
107107
options?: ValidateOptions,
108-
) => Promise<any>;
109-
export type ValidateFields = (nameList?: NamePath[]) => Promise<any>;
108+
) => Promise<Store>;
109+
export type ValidateFields = (nameList?: NamePath[]) => Promise<Store>;
110110

111111
export type NotifyInfo =
112112
| {
@@ -144,8 +144,8 @@ export interface InternalHooks {
144144

145145
export interface FormInstance {
146146
// Origin Form API
147-
getFieldValue: (name: NamePath) => any;
148-
getFieldsValue: (nameList?: NamePath[]) => any;
147+
getFieldValue: (name: NamePath) => StoreValue;
148+
getFieldsValue: (nameList?: NamePath[]) => Store;
149149
getFieldError: (name: NamePath) => string[];
150150
getFieldsError: (nameList?: NamePath[]) => FieldError[];
151151
isFieldsTouched: (nameList?: NamePath[]) => boolean;
@@ -173,6 +173,9 @@ export type InternalFormInstance = Omit<FormInstance, 'validateFields'> & {
173173
getInternalHooks: (secret: string) => InternalHooks | null;
174174
};
175175

176+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
177+
export type EventArgs = any[];
178+
176179
type ValidateMessage = string | (() => string);
177180
export interface ValidateMessages {
178181
default?: ValidateMessage;

0 commit comments

Comments
 (0)