Skip to content

Commit

Permalink
fix(@formily/core): fix onChange trigger times issue#644 (#667)
Browse files Browse the repository at this point in the history
* fix(@formily/core): fix onChange trigger times issue#644

* fix(@formily/core): fix ci
  • Loading branch information
janryWang authored Feb 22, 2020
1 parent 9331f2e commit 4499f9f
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 19 deletions.
82 changes: 81 additions & 1 deletion docs/zh-cn/schema-develop/faq.md
Original file line number Diff line number Diff line change
@@ -1 +1,81 @@
# 介绍
```jsx
import React, { useState } from "react";
import { SchemaForm } from "@formily/antd";
import { setup } from '@formily/antd-components'
import "antd/dist/antd.css";

setup();

export default () => {
const example1Schame = {
type: "object",
properties: {
text: {
title: "例子111",
default: "例子111",
type: "string"
},
link: {
title: "跳转链接",
type: "string",
"x-rules": "url"
},
newTable: {
title: "在新 Tab 中打开",
type: "boolean",
default: false
}
}
};
const example1Value = {
text: "例子111",
newTable: false,
link: "https://www.qq.com"
};
const example2Schame = {
type: "object",
properties: {
xxxx: {
title: "例子222",
default: "例子222",
type: "string"
},
deliverParams: {
title: "透传 URL 参数",
type: "boolean",
default: true
}
}
};
const example2Value = {
xxxx: "例子222",
deliverParams: false
};
const [value, setValue] = useState(example1Value);
const [schema, setSchema] = useState(example1Schame);
return (
<>
<button
onClick={() => {
if (value.xxxx === "例子222") {
setValue(example1Value);
setSchema(example1Schame);
return;
}
setValue(example2Value);
setSchema(example2Schame);
}}
>
点击切换,看 Console ,onChange 会触发很多次
</button>
<SchemaForm
value={value}
defaultValue={value}
schema={schema}
onChange={e => console.log(JSON.stringify(e, null, 2))} // {input:'this is your input string'}
/>
</>
);
};

```
26 changes: 15 additions & 11 deletions packages/core/src/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ const deepValues = {
}
}

const sleep = (d = 1000) =>
new Promise(resolve => {
setTimeout(() => {
resolve()
}, d)
})

describe('createForm', () => {
test('values', () => {
const form = createForm({
Expand Down Expand Up @@ -111,19 +118,15 @@ describe('createForm', () => {
expect(form.getFormGraph()).toMatchSnapshot()
})

const sleep = (d=1000)=>new Promise((resolve)=>{
setTimeout(()=>{
resolve()
},d)
})

test('invalid initialValue will not trigger validate', async () => {
const form = createForm()
const field = form.registerField({
name: 'aa',
rules:[{
required:true
}]
rules: [
{
required: true
}
]
})
const mutators = form.createMutators(field)
field.subscribe(() => {
Expand All @@ -135,7 +138,7 @@ describe('createForm', () => {
}
})
await sleep(10)
expect(field.getState(state=>state.errors).length).toEqual(1)
expect(field.getState(state => state.errors).length).toEqual(1)
})

test('lifecycles', () => {
Expand Down Expand Up @@ -1587,7 +1590,7 @@ describe('major sences', () => {
expect(form.getFormGraph()).toMatchSnapshot()
})

test('visible onChange', () => {
test('visible onChange', async () => {
const onChangeHandler = jest.fn()
const form = createForm({
initialValues: {
Expand All @@ -1601,6 +1604,7 @@ describe('major sences', () => {
form.setFieldState('aa', state => {
state.visible = false
})
await sleep(10)
expect(onChangeHandler).toBeCalledTimes(1)
})

Expand Down
11 changes: 9 additions & 2 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,10 @@ export function createForm<FieldProps, VirtualFieldProps>(
}
if (valuesChanged) {
if (isFn(options.onChange)) {
options.onChange(clone(published.values))
clearTimeout(env.onChangeTimer)
env.onChangeTimer = setTimeout(() => {
options.onChange(clone(published.values))
})
}
heart.publish(LifeCycleTypes.ON_FORM_VALUES_CHANGE, state)
}
Expand Down Expand Up @@ -250,7 +253,10 @@ export function createForm<FieldProps, VirtualFieldProps>(

const notifyFormValuesChange = () => {
if (isFn(options.onChange)) {
options.onChange(state.getSourceState(state => clone(state.values)))
clearTimeout(env.onChangeTimer)
env.onChangeTimer = setTimeout(() => {
options.onChange(state.getSourceState(state => clone(state.values)))
})
}
heart.publish(LifeCycleTypes.ON_FORM_VALUES_CHANGE, state)
}
Expand Down Expand Up @@ -1255,6 +1261,7 @@ export function createForm<FieldProps, VirtualFieldProps>(
})
const env = {
validateTimer: null,
onChangeTimer: null,
graphChangeTimer: null,
leadingStage: false,
publishing: {},
Expand Down
10 changes: 5 additions & 5 deletions packages/react-schema-renderer/src/__tests__/dynamic.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -470,22 +470,22 @@ test('dynamic change functions onChange/onReset/onSubmit/onValidateFailed', asyn
initialValues={constState}
onChange={() => {
if (constState.testA !== '123') {
act(() => setState({ testB: '456' }))
act(() => setState({ ...constState, testB: '456' }))
}
}}
onReset={() => {
if (constState.testA !== '123') {
act(() => setState({ testC: '456' }))
act(() => setState({ ...constState, testC: '456' }))
}
}}
onSubmit={() => {
if (constState.testA !== '123') {
act(() => setState({ testD: '456' }))
act(() => setState({ ...constState, testD: '456' }))
}
}}
onValidateFailed={p => {
if (constState.testA !== '123') {
act(() => setState({ testE: '456' }))
act(() => setState({ ...constState, testE: '456' }))
}
}}
>
Expand Down Expand Up @@ -519,7 +519,7 @@ test('dynamic change functions onChange/onReset/onSubmit/onValidateFailed', asyn
}
const { queryByTestId, queryByText } = render(<TestComponent />)

await sleep(100)
await sleep(30)
fireEvent.click(queryByTestId('radio-a2'))
await wait()
expect(queryByText('valueB-456')).toBeVisible()
Expand Down

0 comments on commit 4499f9f

Please sign in to comment.