Jhig85
Jhig85

Reputation: 355

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>
  )
);

Upvotes: 3

Views: 6787

Answers (2)

Avaneesh Tripathi
Avaneesh Tripathi

Reputation: 194

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.

Upvotes: 4

codeanjero
codeanjero

Reputation: 694

You may also just bind the props like so :

const Child = (props) => {
  const onClick = props.onClick;
  return(<div><p>
  {onClick()}
  </p>
  </div>
  );
}

/* Parent Component */
const ParentEl = () => {
  const onClick = ()=>{return "hi"};

  return (
    <div>
      <Child onClick={onClick} />
    </div>
  )
}

/*Child Component*/


export default function App() {
  return (
    <div className="App">
      <ParentEl />
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

or a codesandbox link to see directly what it does :

https://codesandbox.io/s/hidden-water-s8qjj?file=/src/App.js

here : const onClick = props.onClick; in the child component is doing all the magic

Upvotes: 0

Related Questions