Reputation: 10567
I made a useInput
hook that looks like this.
export function useInput({
type,
name,
placeholder,
initialValue,
helpText,
required,
onKeyUp,
errorMessage,
}: Props) {
const [value, setValue] = useState(initialValue)
const input =
type === 'textarea' ? (
<div className="form-group">
<label>{name}</label>
<span>{helpText}</span>
<textarea
name="email"
className="form-control"
required={required}
id={name}
value={value}
aria-describedby={name}
placeholder={placeholder}
onChange={(e) => setValue(e.target.value)}
/>
</div>
) : (
<div className="form-group">
<label>{name}</label>
<span>{helpText}</span>
<input
type={type}
name="email"
className="form-control"
id={name}
required={required}
value={value}
aria-describedby={name}
placeholder={placeholder}
onChange={(e) => setValue(e.target.value)}
onKeyUp={onKeyUp}
/>
<>{errorMessage}</>
</div>
)
return [value, input]
}
In my pages, I can simply use the hook, like below
const [description, descriptionInput] = useInput({
type: 'textarea',
name: 'Description',
helpText: <small className="muted"> (Optional)</small>,
placeholder: 'I found this interesting because...',
})
and inside the render function use them as {descriptionInput}
and the value will be available in description
.
However, I'm looking for ways to update the value programmatically - to be specific, to reset the value of inputs on form submission for example. All I have is a reference to the input, and the value itself. Is there a nice way to keep using the hook and reset the value at will?
Upvotes: 0
Views: 61
Reputation: 281626
You can simply expose a reset function from your hook which you can call to reset the state to either the initialValue or empty
export function useInput({
type,
name,
placeholder,
initialValue,
helpText,
required,
onKeyUp,
errorMessage,
}: Props) {
const [value, setValue] = useState(initialValue);
const resetInput = useCallback(() => {
setValue(initialValue || "" );
}, [])
const input =
type === 'textarea' ? (
<div className="form-group">
<label>{name}</label>
<span>{helpText}</span>
<textarea
name="email"
className="form-control"
required={required}
id={name}
value={value}
aria-describedby={name}
placeholder={placeholder}
onChange={(e) => setValue(e.target.value)}
/>
</div>
) : (
<div className="form-group">
<label>{name}</label>
<span>{helpText}</span>
<input
type={type}
name="email"
className="form-control"
id={name}
required={required}
value={value}
aria-describedby={name}
placeholder={placeholder}
onChange={(e) => setValue(e.target.value)}
onKeyUp={onKeyUp}
/>
<>{errorMessage}</>
</div>
)
return [value, input, resetInput]
}
and use it like
const [description, descriptionInput, resetDescriptionInput] = useInput({
type: 'textarea',
name: 'Description',
helpText: <small className="muted"> (Optional)</small>,
placeholder: 'I found this interesting because...',
})
P.S. However, since this hook is actually returning JSX content, you could write it as a component too and expose a function to be used by a ref with useImperativeHandle
Upvotes: 1