From d9a24d447a908b16376d5cfd346c9d31129b75a1 Mon Sep 17 00:00:00 2001 From: janryWang Date: Fri, 26 Apr 2019 15:39:34 +0800 Subject: [PATCH] fix(@uform/core): fix setFormState Promise resolve is not wait rerender completed. --- packages/core/src/form.js | 37 ++++++++++++-------- packages/react/src/__tests__/actions.spec.js | 28 +++++++++++++++ packages/utils/src/defer.js | 13 +++++++ packages/utils/src/index.js | 1 + 4 files changed, 65 insertions(+), 14 deletions(-) create mode 100644 packages/react/src/__tests__/actions.spec.js create mode 100644 packages/utils/src/defer.js diff --git a/packages/core/src/form.js b/packages/core/src/form.js index b0e3a9f62a3..8537fbb60f0 100644 --- a/packages/core/src/form.js +++ b/packages/core/src/form.js @@ -17,7 +17,8 @@ import { caf, isChildField, getSchemaNodeFromPath, - BufferList + BufferList, + defer } from './utils' import { Field } from './field' import { runValidation, format } from '@uform/validator' @@ -166,24 +167,21 @@ export class Form { setFormState = reducer => { if (!isFn(reducer)) return - return new Promise(resolve => { - const published = this.publishState() - reducer(published, reducer) - this.checkState(published) - resolve() - }) + const published = this.publishState() + reducer(published, reducer) + return Promise.resolve(this.checkState(published)) } checkState(published) { if (!isEqual(this.state.values, published.values)) { this.state.values = published.values this.state.dirty = true - this.updateFieldsValue() + return this.updateFieldsValue() } if (!isEqual(this.state.initialValues, published.initialValues)) { this.state.initialValues = published.initialValues this.state.dirty = true - this.updateFieldInitialValue() + return this.updateFieldInitialValue() } } @@ -438,20 +436,29 @@ export class Form { } updateFieldsValue(validate = true) { + const { promise, resolve } = defer() + const update = () => { + const updateList = [] each(this.fields, (field, name) => { let newValue = this.getValue(name) field.updateState(state => { state.value = newValue }) if (field.dirty) { - raf(() => { - if (this.destructed) return - field.notify() - this.triggerEffect('onFieldChange', field.publishState()) - }) + updateList.push( + new Promise(resolve => { + raf(() => { + if (this.destructed) return + field.notify() + this.triggerEffect('onFieldChange', field.publishState()) + resolve() + }) + }) + ) } }) + resolve(Promise.all(updateList)) } if (this.state.dirty && this.initialized) { if (validate) { @@ -463,6 +470,8 @@ export class Form { update() } } + + return promise } updateChildrenVisible(parent, visible) { diff --git a/packages/react/src/__tests__/actions.spec.js b/packages/react/src/__tests__/actions.spec.js new file mode 100644 index 00000000000..306c5ed5652 --- /dev/null +++ b/packages/react/src/__tests__/actions.spec.js @@ -0,0 +1,28 @@ +import React from 'react' +import SchemaForm, { + Field, + registerFormField, + connect, + createAsyncFormActions +} from '../index' +import { render } from 'react-testing-library' + +beforeEach(() => { + registerFormField('string', connect()(props =>
{props.value}
)) +}) + +test('createFormActions', async () => { + const actions = createAsyncFormActions() + const TestComponent = () => ( + + + + ) + + const { queryByText } = render() + await sleep(33) + await actions.setFormState(state => (state.values = { aaa: 123 })) + expect(queryByText('123')).toBeVisible() + await actions.setFieldState('aaa', state => (state.value = 'hello world')) + expect(queryByText('hello world')).toBeVisible() +}) diff --git a/packages/utils/src/defer.js b/packages/utils/src/defer.js new file mode 100644 index 00000000000..d6f48f4637d --- /dev/null +++ b/packages/utils/src/defer.js @@ -0,0 +1,13 @@ +export const defer = () => { + let _resolve + let _reject + const promise = new Promise((resolve, reject) => { + _resolve = resolve + _reject = reject + }) + return { + promise, + resolve: _resolve, + reject: _reject + } +} diff --git a/packages/utils/src/index.js b/packages/utils/src/index.js index d141ff9aa6c..eb391ebb342 100644 --- a/packages/utils/src/index.js +++ b/packages/utils/src/index.js @@ -8,3 +8,4 @@ export * from './schema' export * from './lru' export * from './isEmpty' export * from './case' +export * from './defer'