I have a child input component and parent where I set value.
Parent component
const \[dummyText, setDummyText\] = useState('')
return (
<Input
{...props}
id="first-name"
label="First name"
type="text"
placeholder="Please enter your first name"
value={dummyText}
onChange={(value) => setDummyText(value.target.value)}
/>
)
Child input component
import React, { InputHTMLAttributes, forwardRef } from 'react'
export type Props = {} & InputHTMLAttributes<HTMLInputElement>
const FormInput: React.FC<Props> = forwardRef<HTMLInputElement, Partial<Props>>(
({ ...props }, ref) => <input ref={ref} {...props} />
)
FormInput.displayName = 'FormInput'
export default FormInput
I want to add button in child component where on click I need to clear the value.
The thing is that I want to have clear functionality in child component and I do not want to write extra code for every <Input in parent, and whatever I do in child component, I just can't override props.value.
Does anybody have any experience how to solve this?
If you want to clear the input value you can pass the clearing function as a prop to the child component like this:
const Input = ({ onClearInput, ...otherProps }) => {
return (
<div style={{ display: 'flex', gap: '.5rem' }}>
<input {...otherProps} />
<button onClick={onClearInput}>Clear</button>
</div>
);
};
export default function App() {
const [firstName, setFirstName] = useState('');
const [secondName, setSecondName] = useState('');
const onClearInputHandler = (handler) => handler('');
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '.5rem' }}>
<Input
id="first-name"
label="First name"
type="text"
placeholder="Please enter your first name"
value={firstName}
onChange={(event) => setFirstName(event.target.value)}
onClearInput={() => onClearInputHandler(setFirstName)}
/>
<Input
id="second-name"
label="Second name"
type="text"
placeholder="Please enter your second name"
value={secondName}
onChange={(event) => setSecondName(event.target.value)}
onClearInput={() => onClearInputHandler(setSecondName)}
/>
</div>
);
}
Because you'll have a different state for each input you can pass the set
function from useState
as a parameter and run it inside the onClearInputHandler
to clear the value.
Edit:
Then I think the easiest solutions is to handle the clear
function inside the input itself like this:
const Input = (props) => {
const [value, setValue] = useState(props.value || '');
return (
<div style={{ display: 'flex', gap: '.5rem' }}>
<input
{...props}
value={value}
onChange={(event) => setValue(event.target.value)}
/>
<button onClick={() => setValue('')}>Clear</button>
</div>
);
};
export default function App() {
const onSubmitHandler = (event) => {
event.preventDefault();
const formData = new FormData(event.target);
const formProps = Object.fromEntries(formData);
console.log(formProps);
};
return (
<form action="submit" onSubmit={onSubmitHandler}>
<div style={{ display: 'flex', flexDirection: 'column', gap: '.5rem' }}>
<Input
id="first-name"
label="First name"
type="text"
placeholder="Please enter your first name"
name="first-name"
/>
<Input
id="second-name"
label="Second name"
type="text"
placeholder="Please enter your second name"
name="second-name"
/>
</div>
<button type="submit" style={{ margin: '.5rem 0' }}>
Submit
</button>
</form>
);
All inputs are inside the form
and you can read the values when the form is submitted. Otherwise you'll have to create a new state
or ref
for every single Input
you have in your parent component. This way the input value and the handler to clear it are always inside the Input
component.
Here's a demo on stackblitz: https://stackblitz.com/edit/react-gnyvav?file=src%2FApp.js