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

feat: Add StateForm #292

Closed
wants to merge 50 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
9b28f9d
init StateForm
zombieJ May 17, 2019
856f06b
tmp test
zombieJ May 18, 2019
5239a95
External store
zombieJ May 18, 2019
19680c1
support render props
zombieJ May 18, 2019
8039e35
add now
zombieJ May 18, 2019
d6ac84c
lock rc-tools version
zombieJ May 18, 2019
46744ab
sample of useForm
zombieJ May 18, 2019
115dcbd
use getFieldsValue instead of getStore
zombieJ May 19, 2019
a8ea903
render props also support component update check
zombieJ May 19, 2019
3a84a85
adjust value check logic
zombieJ May 20, 2019
6179901
add trigger
zombieJ May 20, 2019
725d772
fix ts error
zombieJ May 20, 2019
cbaa78f
register Field directly
zombieJ May 20, 2019
ae1b74b
add isSimular
zombieJ May 20, 2019
d8c8745
update demo
zombieJ May 20, 2019
a5f178a
render props validate
zombieJ May 20, 2019
6603f3e
cache error
zombieJ May 20, 2019
803aa91
remove should component update
zombieJ May 21, 2019
d7222eb
add description
zombieJ May 21, 2019
d366fb4
update validate logic
zombieJ May 21, 2019
b5a293c
update gitignore
zombieJ May 21, 2019
c9e8172
update submit logic
zombieJ May 28, 2019
10db2e1
add keys
zombieJ May 28, 2019
7a8420f
update setFieldsValue logic
zombieJ May 28, 2019
34db7ce
support lazy notify Field
zombieJ May 28, 2019
0069125
style layout
zombieJ May 28, 2019
b892fa6
wrap useForm
zombieJ May 28, 2019
885dd1d
fix error logic
zombieJ May 28, 2019
c76d008
support single validateTrigger
zombieJ May 28, 2019
ad88444
add getFieldValue
zombieJ May 29, 2019
2a97baa
support touch
zombieJ May 29, 2019
5ea94dc
support isFieldValidating
zombieJ May 29, 2019
1b93e5d
fix validating not works
zombieJ May 29, 2019
b37f375
support initial values
zombieJ May 29, 2019
bf7d901
add reset interface
zombieJ May 29, 2019
8e7fe87
support reset
zombieJ May 29, 2019
d5b7add
support setFields
zombieJ May 30, 2019
3011cc9
refactor
zombieJ May 30, 2019
a1571c9
rename interface
zombieJ May 31, 2019
4346314
support dependencies
zombieJ Jun 3, 2019
558da19
update example
zombieJ Jun 3, 2019
00e4272
opt errors
zombieJ Jun 3, 2019
7fa6008
add props for redux
zombieJ Jun 3, 2019
933a255
supprot redux
zombieJ Jun 3, 2019
b77f543
fix errors
zombieJ Jun 4, 2019
b09c682
fix check meta logic
zombieJ Jun 4, 2019
2aac0b1
update demo
zombieJ Jun 4, 2019
56e3705
support list
zombieJ Jun 4, 2019
45871ab
suport list remove
zombieJ Jun 4, 2019
18f820f
wrap entities api
zombieJ Jun 4, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
34 changes: 23 additions & 11 deletions examples/StateForm-redux.tsx
Expand Up @@ -24,8 +24,8 @@ let App: any = ({ dispatch, fields }) => {
return (
<StateForm
fields={fields}
onValuesChange={values => {
console.log('Value Change:', values);
onValuesChange={(changedValues, allValues) => {
console.log('Value Change:', changedValues, allValues);
}}
onFieldsChange={(changedFields, allFields) => {
console.log('Field Change:', changedFields, allFields);
Expand All @@ -42,15 +42,27 @@ let App: any = ({ dispatch, fields }) => {
<Input />
</LabelField>

<button onClick={() => {
dispatch({
type: 'updateFields',
fields: [{
name: 'field',
value: 'redux it!',
}],
});
}}>dispatch to change</button>
<LabelField name="required" placeholder="required" rules={[{ required: true }]}>
<Input />
</LabelField>

<button
onClick={() => {
dispatch({
type: 'updateFields',
fields: [
{
name: 'field',
value: 'redux it!',
touched: true,
validating: true,
},
],
});
}}
>
dispatch to change
</button>
</StateForm>
);
};
Expand Down
21 changes: 12 additions & 9 deletions src/StateForm/StateFormField.tsx
Expand Up @@ -124,15 +124,17 @@ class StateFormField extends React.Component<StateFormFieldProps, StateFormField
break;

case 'setField': {
const { data } = info;
if ('touched' in data) {
this.touched = data.touched;
}
if ('validating' in data) {
this.validatePromise = data.validating ? Promise.resolve() : null;
}
if (namePathList && containsNamePath(namePathList, namePath)) {
const { data } = info;
if ('touched' in data) {
this.touched = data.touched;
}
if ('validating' in data) {
this.validatePromise = data.validating ? Promise.resolve() : null;
}

this.forceUpdate();
this.forceUpdate();
}
break;
}

Expand Down Expand Up @@ -196,10 +198,11 @@ class StateFormField extends React.Component<StateFormFieldProps, StateFormField

// ============================= Child Component =============================
public getMeta = (): Meta => {
const { name } = this.props;
const { getFieldError } = this.context;
// Make error & validating in cache to save perf
this.prevValidating = this.isFieldValidating();
this.prevErrors = getFieldError(name);
this.prevErrors = getFieldError(getNamePath(name));

const meta: Meta = {
touched: this.isFieldTouched(),
Expand Down
2 changes: 1 addition & 1 deletion src/StateForm/interface.ts
Expand Up @@ -77,6 +77,6 @@ export type NotifyInfo =
};

export interface Callbacks {
onValuesChange?: (values: Store) => void;
onValuesChange?: (changedValues: Store, values: Store) => void;
onFieldsChange?: (changedFields: FieldData[], allFields: FieldData[]) => void;
}
33 changes: 22 additions & 11 deletions src/StateForm/useForm.ts
Expand Up @@ -16,6 +16,7 @@ import { allPromiseFinish } from './utils/asyncUtil';
import NameMap from './utils/NameMap';
import { ErrorCache } from './utils/validateUtil';
import {
cloneByNamePathList,
containsNamePath,
getNamePath,
getValue,
Expand Down Expand Up @@ -262,18 +263,14 @@ export class FormStore {
this.validateFields(childrenFields);

// trigger callback function
const { onValuesChange, onFieldsChange } = this.callbacks;
const { onValuesChange } = this.callbacks;

if (onValuesChange) {
onValuesChange(this.store);
}
if (onFieldsChange) {
const fields = this.getFields();
const changedField = fields.find(({ name: fieldName }) => {
return matchNamePath(fieldName as any, namePath);
});
onFieldsChange([changedField], fields);
const changedValues = cloneByNamePathList(this.store, [namePath]);
onValuesChange(changedValues, this.store);
}

this.triggerOnFieldsChange([namePath]);
};

// Let all child Field get update.
Expand Down Expand Up @@ -326,6 +323,18 @@ export class FormStore {
return childrenFields;
};

private triggerOnFieldsChange = (namePathList: InternalNamePath[]) => {
const { onFieldsChange } = this.callbacks;

if (onFieldsChange) {
const fields = this.getFields();
const changedFields = fields.filter(({ name: fieldName }) => {
return containsNamePath(namePathList, fieldName as any);
});
onFieldsChange(changedFields, fields);
}
};

// =========================== Validate ===========================
private validateFields: ValidateFields = (nameList?: NamePath[], options?: ValidateOptions) => {
const namePathList: InternalNamePath[] | undefined = nameList && nameList.map(getNamePath);
Expand Down Expand Up @@ -363,9 +372,11 @@ export class FormStore {
summaryPromise
.catch(results => results)
.then((results: FieldError[]) => {
const resultNamePathList: InternalNamePath[] = results.map(({ name }) => name);

this.errorCache.updateError(results);
console.log('>????', results);
this.notifyObservers(this.store, results.map(({ name }) => name), { type: 'errorUpdate' });
this.notifyObservers(this.store, resultNamePathList, { type: 'errorUpdate' });
this.triggerOnFieldsChange(resultNamePathList);
});

const returnPromise = summaryPromise
Expand Down
10 changes: 10 additions & 0 deletions src/StateForm/utils/valueUtil.ts
Expand Up @@ -27,6 +27,16 @@ export function setValue(store: any, namePath: InternalNamePath, value: any) {
return newStore;
}

export function cloneByNamePathList(store: any, namePathList: InternalNamePath[]) {
let newStore = {};
namePathList.forEach(namePath => {
const value = getValue(store, namePath);
newStore = setValue(store, namePath, value);
});

return newStore;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感觉怪怪的,setValue 调用了 n 次。

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

以前也是这么做的,它要出一个纯粹的 Field 需要填一下对应的值。不过这里其实每次都只有一个 Field 变更,并不是真的一串值变了。

ref: https://github.com/react-component/form/blob/master/src/createBaseForm.js#L294

}

export function containsNamePath(namePathList: InternalNamePath[], namePath: InternalNamePath) {
return namePathList && namePathList.some(path => matchNamePath(path, namePath));
}
Expand Down