diff --git a/packages/react/src/__tests__/form.spec.tsx b/packages/react/src/__tests__/form.spec.tsx index bdbe939fd92..525b391f743 100644 --- a/packages/react/src/__tests__/form.spec.tsx +++ b/packages/react/src/__tests__/form.spec.tsx @@ -1,12 +1,14 @@ -import React from 'react' +import React, { useState } from 'react' import { Form, Field, createFormActions, FormEffectHooks, - IFieldStateUIProps + IFieldStateUIProps, + FormSpy, } from '../index' -import { render } from '@testing-library/react' +import { render, fireEvent, waitForElement } from '@testing-library/react' +import { LifeCycleTypes } from '@uform/core' const Input: React.FC = props => ( @@ -60,6 +62,78 @@ describe('test all apis', () => { await actions.submit() expect(onSubmitHandler).toBeCalledWith({ aaa: 'hello world' }) }) + + test('onSubmit async', async () => { + const actions = createFormActions() + const onSubmitEndHandler = jest.fn() + const App = () => { + return
+
{ + return new Promise((resolve) => { + setTimeout(resolve) + }) + }} + actions={actions} + > + + + {({ type }) => { + return + }} + +
+
+ } + const { getByTestId, queryByTestId } = render() + + expect(onSubmitEndHandler).toBeCalledTimes(0) + fireEvent.click(queryByTestId('submit')) + const submitEle = await waitForElement( + () => getByTestId('submit') + ) + + expect(submitEle.textContent).not.toEqual(LifeCycleTypes.ON_FORM_INIT) + }) + + test('onSubmit unmount promise', async () => { + const actions = createFormActions() + const onSubmitEndHandler = jest.fn() + const App = () => { + const [visible, setVisible] = useState(true) + return
+ {visible ?
{ + return new Promise((resolve) => { + setVisible(false) + setTimeout(resolve) + }) + }} + actions={actions} + > + + + {({ type }) => { + return + }} + +
: null } +
+ } + const { getByTestId, queryByTestId } = render() + + expect(onSubmitEndHandler).toBeCalledTimes(0) + fireEvent.click(queryByTestId('submit')) + const submitEle = await waitForElement( + () => getByTestId('submit') + ) + + expect(submitEle.textContent).toEqual(LifeCycleTypes.ON_FORM_INIT) + }) }) describe('major scenes', () => { diff --git a/packages/react/src/hooks/useFormSpy.ts b/packages/react/src/hooks/useFormSpy.ts index 0c6778e7d32..c6b365d4d75 100644 --- a/packages/react/src/hooks/useFormSpy.ts +++ b/packages/react/src/hooks/useFormSpy.ts @@ -16,15 +16,17 @@ export const useFormSpy = (props: IFormSpyProps): ISpyHook => { const broadcast = useContext(BroadcastContext) const form = useContext(FormContext) const initializedRef = useRef(false) + const unmountRef = useRef(false) const subscriberId = useRef() const [type, setType] = useState(LifeCycleTypes.ON_FORM_INIT) const [state, dispatch] = useReducer( (state, action) => props.reducer(state, action, form), {} ) - const subscriber = useCallback(({ type, payload }) => { + const subscriber = useCallback(({ type, payload }) => { if (initializedRef.current) return setTimeout(() => { + if (unmountRef.current) return if (isStr(props.selector) && FormPath.parse(props.selector).match(type)) { setType(type) dispatch({ @@ -56,6 +58,7 @@ export const useFormSpy = (props: IFormSpyProps): ISpyHook => { } else if (broadcast) { broadcast.unsubscribe(subscriberId.current) } + unmountRef.current = true } }, []) const formApi: IForm = form ? form : broadcast && broadcast.getContext()