Sooraj
Sooraj

Reputation: 10567

Reseting value of input element using React Hooks

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

Answers (1)

Shubham Khatri
Shubham Khatri

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

Related Questions