38

I have a component that uses a hook to set the input value into component state. I want to add a class when the input value is more than 0 characters in length, however I'm coming across an issue where TypeScript says my ref may be undefined.

I can't get rid of this error even if I check if the ref exists in the conditional that wraps the code to add the class. I'm not sure on the solution to this.

Error: Object is possibly 'undefined' on inputValue.current.classList.add(inputHasContentClassName);

import React, { useState, useEffect, useRef } from 'react';

const Component: React.FC = () => {
  const [inputValue, setInputValue] = useState('');
  const myRef = useRef();

  useEffect(() => {
    const inputHasContentClassName = 'input--has-value';

    if (inputValue.length > 0 && inputValue) {
      inputValue.current.classList.add(inputHasContentClassName);
    } else {
      inputValue.current.classList.remove(inputHasContentClassName);
    }
  }, [inputValue]);

  function handleInputChange(e: React.FormEvent<HTMLInputElement>) {
    setInputValue(e.currentTarget.value);
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();

    console.log('Submit form');
  }

  return (
    <>
      <section>
        <form onSubmit={handleSubmit}>
          <div>
            <input
              ref={myRef}
              onChange={handleInputChange}
              type="number"
            />
            <label>Input Label</label>
          </div>
          <button
            type="submit"
            disabled={inputValue.length === 0}
          >
            Submit
          </button>
        </form>
      </section>
    </>
  );
};

export default Component;
2
  • just add an if like , if (myRef !== null) then do rest actions Commented Jan 24, 2020 at 18:29
  • Is this code edited after the accepted answer has been given? It seems the inputValue has been a ref maybe, but now is just a string. Commented Jun 26, 2023 at 11:39

2 Answers 2

52

useRef() returns an object with a current property, which contains the object you actually care about. And before the first render is complete, that current property will be null. This means the type of that ref is:

{ current: WhateverTypeYouCareAbout | null }

And that means you have to handle null as a possible value of the current property. But the ref object itself will always exist, it's just that its current property may be null.

I would simply store the current value of your ref in a variable, test that existence, and then use it.

  useEffect(() => {
    const inputHasContentClassName = 'input--has-value';
    const inputElement = inputValue.current;        

    if (inputElement && inputElement.value.length > 0) {
      inputElement.classList.add(inputHasContentClassName);
    } else {
      inputElement.classList.remove(inputHasContentClassName);
    }
  }, [inputValue]);

You can also tell the TypeScript compiler the type of your ref (in this case HTMLInputElement) by doing the following:

const myRef = useRef<HTMLInputElement>();
Sign up to request clarification or add additional context in comments.

5 Comments

This resolves the initial error but I then get "classList" does not exist on type "never" even if I check for inputElement: inputElement && inputElement.classList.add('classname')
Managed to solve it with const inputElement = (myRef.current as unknown) as HTMLInputElement; but this feels like a hack.
Try useRef<HTMLInputElement>();
@AlexWayne - Thank you :-) useRef<HTMLInputElement>();
Don't use ref as a hook dependency. This is not reliable, as mutating the ref won't trigger a re-render: stackoverflow.com/questions/60476155/…
1

Following this blog https://medium.com/@dimterion/modals-with-html-dialog-element-in-javascript-and-react-fb23c885d62e with my Dialog component. I got the ref.current my be possibly undefined and adding the type helped clear the error.

const DeleteDialogue = ({ showModal, hideModal, firstName, deleteUser }) => {
  //if (!showModal) return null
  const ref = useRef<HTMLDialogElement>()

  useMemo(() => {
    if (showModal) {
      ref.current?.showModal()
    } else {
      ref.current?.close()
    }
  }, [showModal])
  return (
    <dialog
      className="modal modal-sheet position-static d-block bg-secondary py-5"
      role="dialog"
      tabIndex={-1}
      id="modalSheet"
      ref={ref}
      onCancel={hideModal}
    >

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.