0

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?

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.