DarkTrick
DarkTrick

Reputation: 3529

React: useRef for multiple components

I have a custom component with multiple sub components like this:

interface MyComponentProps {
  ref: any; 
}; 

function MyComponent(props: MyComponentProps){
  return <>
  <input id="name" type="number" />
  <input id="age" type="text" />
  </>
}

I'd like props.ref to contain values of all subcomponents, when accessed from the outside. Example: myref.current?.value.name and myref.current?.value.age should be possible. How do I do that?

Constraints:

Upvotes: 2

Views: 2549

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 371193

You can create a ref for each other component, then combine those into a single ref.

const App = () => {
    const ref = React.useRef();
    setInterval(() => {
      console.log(ref.current.nameRef.current.value);
      console.log(ref.current.ageRef.current.value);
    }, 1000);
    return <MyComponent combinedRef={ref} />;
};
function MyComponent(props){
  const nameRef = React.useRef();
  const ageRef = React.useRef();
  React.useEffect(() => {
    props.combinedRef.current = { nameRef, ageRef };
  }, []);
  return <div>
    <input id="name" type="number" ref={nameRef} />
    <input id="age" type="text" ref={ageRef} />
  </div>;
}

ReactDOM.createRoot(document.querySelector('.react')).render(<App />);
<script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
<div class='react'></div>

That said, this is a very odd pattern to want to have in React - it doesn't go well at all with how React control flow should usually be, I wouldn't recommend it.

If you must use the exact path myref.current?.value.name, you'll need to make both inputs controlled components, and then inside MyComponent, do:

props.combinedRef.current = {
  value: { // should there really be an extra level of nesting here?
    name,
    age
  }
}

Upvotes: 2

Related Questions