diff --git a/docs/Examples/next/Detail.md b/docs/Examples/next/Detail.md index b5c27488fef..46e4bbf03d2 100644 --- a/docs/Examples/next/Detail.md +++ b/docs/Examples/next/Detail.md @@ -31,6 +31,7 @@ const App = () => { setState(values)} initialValues={state.value} editable={state.editable} labelCol={7} diff --git a/packages/core/src/form.ts b/packages/core/src/form.ts index eac3e9e2e96..899129c3769 100644 --- a/packages/core/src/form.ts +++ b/packages/core/src/form.ts @@ -119,6 +119,10 @@ export class Form { }) } + public isDirtyValues(values: any) { + return !isEmpty(values) && !isEqual(this.state.values, values) + } + public setFieldState = ( path: Path | IFormPathMatcher, callback?: () => void diff --git a/packages/react/src/__tests__/value.spec.js b/packages/react/src/__tests__/value.spec.js index 9b835bcd248..890f6c802b0 100644 --- a/packages/react/src/__tests__/value.spec.js +++ b/packages/react/src/__tests__/value.spec.js @@ -1,10 +1,20 @@ -import React from 'react' -import { render } from '@testing-library/react' -import SchemaForm, { Field, registerFormField, connect } from '../index' +import React, { useState } from 'react' +import { render, act } from '@testing-library/react' +import SchemaForm, { + Field, + registerFormField, + connect, + createFormActions +} from '../index' registerFormField( 'test-string', - connect()(props =>
{typeof props.value}
) + connect()(props => ( + +
{props.value}
+
{typeof props.value}
+
+ )) ) test('default value', async () => { @@ -16,7 +26,7 @@ test('default value', async () => { const { getByTestId } = render() await sleep(33) - expect(getByTestId('value').textContent).toEqual('string') + expect(getByTestId('type-value').textContent).toEqual('string') }) test('initialValues', async () => { @@ -28,5 +38,46 @@ test('initialValues', async () => { const { getByTestId } = render() await sleep(33) - expect(getByTestId('value').textContent).toEqual('string') + expect(getByTestId('type-value').textContent).toEqual('string') +}) + +test('controlled initialValues', async () => { + const actions = createFormActions() + let outerSetState + const Component = () => { + const [state, setState] = useState({ + foo: '123' + }) + outerSetState = values => + act(() => { + setState(values) + }) + return ( + + + + ) + } + + const { getByTestId } = render() + await sleep(33) + expect(getByTestId('type-value').textContent).toEqual('string') + await actions.setFieldState('foo', state => { + state.value = '321' + }) + await actions.reset() + expect(getByTestId('value').textContent).toEqual('123') + await actions.setFieldState('foo', state => { + state.value = '321' + }) + act(() => { + outerSetState({ foo: '123' }) + }) + await sleep(33) + expect(getByTestId('value').textContent).toEqual('123') + await sleep(33) }) diff --git a/packages/react/src/state/form.tsx b/packages/react/src/state/form.tsx index 37e5429a13a..d85951c9be6 100644 --- a/packages/react/src/state/form.tsx +++ b/packages/react/src/state/form.tsx @@ -192,14 +192,11 @@ export const StateForm = createHOC((options, Form) => { public componentDidUpdate(prevProps) { const { value, editable, initialValues } = this.props - if (!isEmpty(value) && !isEqual(value, prevProps.value)) { + if (this.form.isDirtyValues(value)) { this.form.changeValues(value) } - if ( - !isEmpty(initialValues) && - !isEqual(initialValues, prevProps.initialValues) - ) { - this.form.initialize({ initialValues }) + if (this.form.isDirtyValues(initialValues)) { + this.form.initialize({ values: initialValues }) } if (!isEmpty(editable) && !isEqual(editable, prevProps.editable)) { this.form.changeEditable(editable)