Skip to content

Commit

Permalink
Merge pull request #8910 from WiXSL/fix-eh-exec-order
Browse files Browse the repository at this point in the history
Fix custom input's onChange handlers should have access to updated context value
  • Loading branch information
djhi authored Jul 3, 2023
2 parents 0fa640f + caf4d46 commit dd0e500
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 4 deletions.
60 changes: 60 additions & 0 deletions packages/ra-core/src/form/useInput.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,26 @@ const Input: FunctionComponent<
return children(inputProps);
};

const InputWithCustomOnChange: FunctionComponent<
{
children: (props: ReturnType<typeof useInput>) => ReactElement;
} & InputProps & { setContextValue?: (value: string) => void }
> = ({ children, setContextValue, ...props }) => {
const { getValues } = useFormContext();

return (
<Input
{...props}
onChange={e => {
props.onChange(e);
setContextValue(getValues()[props.source]);
}}
>
{children}
</Input>
);
};

describe('useInput', () => {
it('returns the props needed for an input', () => {
let inputProps;
Expand Down Expand Up @@ -106,6 +126,46 @@ describe('useInput', () => {
expect(handleBlur).toHaveBeenCalled();
});

it('custom onChange handler should have access to updated context input value', () => {
let targetValue, contextValue;
const handleChange = e => {
targetValue = e.target.value;
};
const setContextValue = value => {
contextValue = value;
};

render(
<CoreAdminContext dataProvider={testDataProvider()}>
<Form onSubmit={jest.fn()}>
<InputWithCustomOnChange
source="title"
resource="posts"
onChange={handleChange}
setContextValue={setContextValue}
defaultValue=""
>
{({ id, field }) => (
<input
type="text"
id={id}
aria-label="Title"
{...field}
/>
)}
</InputWithCustomOnChange>
</Form>
</CoreAdminContext>
);
const input = screen.getByLabelText('Title');

fireEvent.change(input, {
target: { value: 'Changed title' },
});
expect(targetValue).toBe('Changed title');
expect(contextValue).toBe('Changed title');
});

describe('defaultValue', () => {
it('applies the defaultValue when input does not have a value', () => {
const onSubmit = jest.fn();
Expand Down
8 changes: 4 additions & 4 deletions packages/ra-core/src/form/useInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,21 @@ export const useInput = <ValueType = any>(
useApplyInputDefaultValues(props);

const onBlur = useEvent((...event: any[]) => {
controllerField.onBlur();
if (initialOnBlur) {
initialOnBlur(...event);
}
controllerField.onBlur();
});

const onChange = useEvent((...event: any[]) => {
if (initialOnChange) {
initialOnChange(...event);
}
const eventOrValue = (props.type === 'checkbox' &&
event[0]?.target?.value === 'on'
? event[0].target.checked
: event[0]?.target?.value ?? event[0]) as any;
controllerField.onChange(parse ? parse(eventOrValue) : eventOrValue);
if (initialOnChange) {
initialOnChange(...event);
}
});

const field = {
Expand Down

0 comments on commit dd0e500

Please sign in to comment.