From 827db44053c9db5f486b15a9a2c64009c97547f7 Mon Sep 17 00:00:00 2001 From: Prasanna Date: Sat, 4 Apr 2020 12:13:54 +0530 Subject: [PATCH] Make useInput hook return child's input.value when parent's enhanced input.value is undefined. Closes #4023[https://github.com/marmelab/react-admin/issues/4203]. Issue was caused by useField hook of final-form returning defaultValue of field as undefined (when it is not yet available in state) while enhancing the parent input. useInput hook of react-admin is considering same enhanced input with value undefined while rendering the children. --- packages/ra-core/src/form/useInput.spec.tsx | 37 +++++++++++++++++++ packages/ra-core/src/form/useInput.ts | 8 +++- .../src/input/ReferenceArrayInput.js | 6 +-- .../src/input/ReferenceArrayInput.spec.js | 25 +++++++++++++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/packages/ra-core/src/form/useInput.spec.tsx b/packages/ra-core/src/form/useInput.spec.tsx index fafc8f92a7..b0f04977c1 100644 --- a/packages/ra-core/src/form/useInput.spec.tsx +++ b/packages/ra-core/src/form/useInput.spec.tsx @@ -64,6 +64,43 @@ describe('useInput', () => { expect(inputProps.meta).toBeDefined(); }); + it('allows to override the value of enhanced input', () => { + let inputProps; + const enhancedInput: any = { + id: 'parent', + name: 'title', + isRequired: true, + }; + const meta = { + touched: false, + }; + render( +
( + + {props => { + inputProps = props; + return
; + }} + + )} + /> + ); + + expect(inputProps.id).toEqual('my-title'); + expect(inputProps.input).toBeDefined(); + expect(inputProps.input.value).toEqual('overridden value'); + expect(inputProps.meta).toBeDefined(); + }); + it('allows to extend the input event handlers', () => { const handleBlur = jest.fn(); const handleChange = jest.fn(); diff --git a/packages/ra-core/src/form/useInput.ts b/packages/ra-core/src/form/useInput.ts index 309c4e6e0b..ffff1c4310 100644 --- a/packages/ra-core/src/form/useInput.ts +++ b/packages/ra-core/src/form/useInput.ts @@ -91,10 +91,14 @@ const useInput = ({ // If there is an input prop, this input has already been enhanced by final-form // This is required in for inputs used inside other inputs (such as the SelectInput inside a ReferenceInput) - if (options.input) { + const enhancedInput = options.input; + if (enhancedInput) { return { id: id || source, - input: options.input, + input: { + ...enhancedInput, + value: enhancedInput.value || input.value, + }, meta: options.meta, isRequired: isRequired(validate), }; diff --git a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.js b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.js index 6958246b9d..2efb2938b7 100644 --- a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.js +++ b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.js @@ -96,8 +96,6 @@ const ReferenceArrayInput = ({ onChange, onFocus, validate, - parse, - format, ...props }) => { if (React.Children.count(children) !== 1) { @@ -113,8 +111,8 @@ const ReferenceArrayInput = ({ onFocus, source: props.source, validate, - parse, - format, + parse: props.parse, + format: props.format, }); const controllerProps = useReferenceArrayInputController({ diff --git a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js index 5c8d17597d..a444998c6d 100644 --- a/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js +++ b/packages/ra-ui-materialui/src/input/ReferenceArrayInput.spec.js @@ -159,4 +159,29 @@ describe('', () => { queryByText(JSON.stringify({ touched: false, helperText: false })) ).not.toBeNull(); }); + + it('should pass format and parse props down to child component', () => { + let formatCallback, parseCallback; + const MyComponent = ({ parse, format }) => { + parseCallback = parse; + formatCallback = format; + return
; + }; + const parse = jest.fn(); + const format = jest.fn(); + render( + + + + ); + parseCallback('parse'); + formatCallback('format'); + expect(parse).toBeCalledWith('parse'); + expect(format).toBeCalledWith('format'); + }); });