Skip to content

Commit 8e73cbc

Browse files
authored
Merge pull request marmelab#10665 from marmelab/fix-use-input-default-value
Fix `useInput` default value overrides `null`
2 parents 0a2074a + b447607 commit 8e73cbc

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

packages/ra-core/src/form/useApplyInputDefaultValues.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ export const useApplyInputDefaultValues = ({
4646
if (
4747
defaultValue == null ||
4848
formValue != null ||
49-
recordValue != null ||
49+
// We check strictly for undefined to avoid setting default value
50+
// when the field is null
51+
recordValue !== undefined ||
5052
isDirty
5153
) {
5254
return;

packages/ra-core/src/form/useInput.spec.tsx

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { testDataProvider } from '../dataProvider';
77
import { Form } from './Form';
88
import { useInput, InputProps, UseInputValue } from './useInput';
99
import { required } from './validation/validate';
10+
import { DefaultValue } from './useInput.stories';
1011

1112
const Input: FunctionComponent<
1213
{
@@ -172,30 +173,25 @@ describe('useInput', () => {
172173

173174
describe('defaultValue', () => {
174175
it('applies the defaultValue when input does not have a value', () => {
175-
const onSubmit = jest.fn();
176-
render(
177-
<CoreAdminContext dataProvider={testDataProvider()}>
178-
<Form onSubmit={onSubmit}>
179-
<Input
180-
source="title"
181-
resource="posts"
182-
defaultValue="foo"
183-
>
184-
{({ id, field }) => {
185-
return (
186-
<input
187-
type="text"
188-
id={id}
189-
aria-label="Title"
190-
{...field}
191-
/>
192-
);
193-
}}
194-
</Input>
195-
</Form>
196-
</CoreAdminContext>
197-
);
198-
expect(screen.queryByDisplayValue('foo')).not.toBeNull();
176+
render(<DefaultValue initialValue={undefined} />);
177+
expect(screen.queryByDisplayValue('default value')).not.toBeNull();
178+
});
179+
180+
it('does not apply the defaultValue when input has a value', () => {
181+
render(<DefaultValue initialValue="initial value" />);
182+
expect(screen.queryByDisplayValue('default value')).toBeNull();
183+
expect(screen.queryByDisplayValue('initial value')).not.toBeNull();
184+
});
185+
186+
it('does not apply the defaultValue when input has an empty string value', () => {
187+
render(<DefaultValue initialValue="" />);
188+
expect(screen.queryByDisplayValue('default value')).toBeNull();
189+
});
190+
191+
it('does not apply the defaultValue when input has a null value', () => {
192+
render(<DefaultValue initialValue={null} />);
193+
expect(screen.queryByDisplayValue('default value')).toBeNull();
194+
expect(screen.queryByDisplayValue('')).not.toBeNull();
199195
});
200196

201197
it('does not apply the defaultValue when input has a value of 0', () => {

packages/ra-core/src/form/useInput.stories.tsx

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import * as React from 'react';
22
import { CoreAdminContext } from '../core';
33
import { Form } from './Form';
4-
import { useInput } from './useInput';
4+
import { InputProps, useInput } from './useInput';
55

66
export default {
77
title: 'ra-core/form/useInput',
88
};
99

10-
const Input = ({ source }) => {
11-
const { id, field, fieldState } = useInput({ source });
10+
const Input = (props: InputProps) => {
11+
const { id, field, fieldState } = useInput(props);
1212

1313
return (
1414
<label htmlFor={id}>
@@ -41,3 +41,48 @@ export const Basic = () => {
4141
</CoreAdminContext>
4242
);
4343
};
44+
45+
export const DefaultValue = ({
46+
initialValue,
47+
}: {
48+
initialValue: string | null | undefined;
49+
}) => {
50+
const [submittedData, setSubmittedData] = React.useState<any>();
51+
return (
52+
<CoreAdminContext>
53+
<Form
54+
record={{ field1: initialValue }}
55+
onSubmit={data => setSubmittedData(data)}
56+
>
57+
<div
58+
style={{
59+
display: 'flex',
60+
flexDirection: 'column',
61+
gap: '1em',
62+
marginBottom: '1em',
63+
}}
64+
>
65+
<Input source="field1" defaultValue="default value" />
66+
</div>
67+
<button type="submit">Submit</button>
68+
</Form>
69+
<pre>{JSON.stringify(submittedData, null, 2)}</pre>
70+
</CoreAdminContext>
71+
);
72+
};
73+
74+
DefaultValue.args = {
75+
initialValue: 'valid',
76+
};
77+
78+
DefaultValue.argTypes = {
79+
initialValue: {
80+
options: ['valid', 'null', 'undefined'],
81+
mapping: {
82+
valid: 'initial value',
83+
null: null,
84+
undefined: undefined,
85+
},
86+
control: { type: 'select' },
87+
},
88+
};

0 commit comments

Comments
 (0)