Search code examples
reactjsreact-hooksrefuse-ref

How to set focus on child component's input on a button click in the parent in React Hooks


I have a parent component that has a button with an onClick event and when there is an error I want to focus on an input that is in a child component. I know this can be done using useRef but I keep getting an undefined error. Here is my code:

/* Parent Component */
const parent = () => {
  const acresRef = useRef();
  const addrRef = useRef();

  const acresFocus = () => {
    acresRef.current.focus();
  };

  const addressFocus = () => {
    addrRef.current.focus();
  };

  return (
    <Child addrRef={addrRef} acresRef={acresRef} />
    <button onClick={acresFocus} />
    <button onCLick={addressFocus} />
  )
}

/*Child Component*/
const Child = forwardRef(
  ({props}, acresRef, addrRef) => (
  <div>
    <label for="address">Address</label>
    <input type="text" name="address" ref={addrRef} />
  </div>
  <div>
    <label for="acres">Acres</label>
    <input type="text" name="acres" ref={acresRef} />
  </div>
  )
);

Solution

  • You are incorrectly using refs here. forwardRef works when ref is passed to the component. Anything apart from that is a prop to the component. So in your case, acresRef and addrRef will be received within props by the child component.

    /*Child Component*/
    const Child = (props) => (
      <>
        <div>
          <label htmlFor="address">Address</label>
          <input type="text" name="address" ref={props.addrRef} />
        </div>
        <div>
          <label htmlFor="acres">Acres</label>
          <input type="text" name="acres" ref={props.acresRef} />
        </div>
      </>
    );
    
    /* Parent Component */
    const Parent = () => {
      const acresRef = React.useRef();
      const addrRef = React.useRef();
    
      const acresFocus = () => {
        acresRef.current.focus();
      };
    
      const addressFocus = () => {
        addrRef.current.focus();
      };
    
      return (
        <>
          <Child addrRef={addrRef} acresRef={acresRef} />
          <button onClick={acresFocus}>acres</button>
          <button onClick={addressFocus}>address</button>
        </>
      );
    };
    

    Check this codesandbox here.