Search code examples
reactjstypescriptreact-reduxcomponentsref

Can't access forwareded Ref value in parent component React typescript


I have a situation where i have created a component for input. This is a custom component and i want to access the value entered by user in this input in the parent component(where i am using it).

I am forwarding ref from this Input Component but the parent component is receiving the complete input not the value. How can i use the value. Below is my code.

Input.tsx

  interface AuxProps {
      id :''
    }

const Input = React.forwardRef<HTMLInputElement,AuxProps>((props, ref) => {
  return (      
      <input 
      id={props.id}   
      ref = {ref}         
      defaultValue = '1' 
      type='number' 
      ></input>
  );
});
export default Input;

HeaderComponent.tsx

const HeaderComponent= () => {

  const inputAmount = useRef<HTMLInputElement>(null);
  const addProductHandle = (event: any) => {
    event.preventDefault();
    console.log(inputAmount.current.value);     //<----Error:- object is possibly null
  };
  return (
    <form className={classes["form"]}>
      <Input id="1s" ref={inputAmount}></Input>
      <button onClick={addProductHandle}> + ADD </button>
    </form>
  );
};
export default HeaderComponent;

Not sure how can i use this ref value.


Solution

  • You were close.

    Let's take a look on useRef return type:

      interface RefObject<T> {
            readonly current: T | null;
        }
    

    According to this type signature, current property might be T (in our case HTMLInputElement) or null.

    This is why you are using typescript - to avoid errors on PROD.

    Since current might be null, TS asks you to double check if current exists.

    you can add ? or if condition:

    import React, { useRef, MouseEventHandler } from 'react'
    
    interface AuxProps {
        id: string
    }
    
    const Input = React.forwardRef<HTMLInputElement, AuxProps>((props, ref) => {
        return (
            <input
                id={props.id}
                ref={ref}
                defaultValue='1'
                type='number'
            ></input>
        );
    });
    
    
    const HeaderComponent = () => {
    
        const inputAmount = useRef<HTMLInputElement>(null);
        const addProductHandle: MouseEventHandler<HTMLButtonElement> = (event) => {
    
            event.preventDefault();
            console.log(inputAmount.current?.value);     // ok 
            if (inputAmount.current) {
                console.log(inputAmount.current.value); //ok
            }
        };
        return (
            <form >
                <Input id="1s" ref={inputAmount}></Input>
                <button onClick={addProductHandle}> + ADD </button>
            </form>
        );
    };
    export default HeaderComponent;
    

    Btw, you can use MouseEventHandler<HTMLButtonElement> for click handlers. See my example