Alexander Craggs
Alexander Craggs

Reputation: 8759

How to provide a ref to a child element

I have two functions:

export default function Example() {
  return (
    <Widget>
      <img src="/hello" />
    </Widget>
  )
}

export default function Widget() {
  const ref = useRef(null)
  return (
    <div>
      {children}
    </div>
  )
}

How do I apply 'ref' to the image element of Example? Is there a way to always apply it to the first child element?

Upvotes: 0

Views: 179

Answers (2)

Adam Cai
Adam Cai

Reputation: 387

You can use React's Context.

const MyContext = React.createContext();

function Widget(props) {
  const myRef = useRef(null);
  useEffect(() => {
    myRef.current.focus();
  });
  return (
    <MyContext.Provider value={myRef}>{props.children}</MyContext.Provider>
  );
}

function Example() {
  return (
    <Widget>
      <MyContext.Consumer>
        {(forwardedRef) => <input type="text" ref={forwardedRef} />}
      </MyContext.Consumer>
    </Widget>
  );
}

I created a demo for you: https://codesandbox.io/s/prod-voice-mkrcp

Upvotes: 0

P4R3A
P4R3A

Reputation: 1099

you can use cloneElement which helps us to clone and return a new React element using an element as the starting point. by this, we can add ref to element props, first, we made an array of childrens, then add our ref to the first one, e.g:

function Wrapper({ children }) {
  const testRef = React.useRef(undefined);

  const addReftoFirstChild = (chilrens, ref) => {
    let elements = React.Children.toArray(chilrens);

    return [React.cloneElement(elements[0], { ref })].concat(elements.slice(1));
  };

  return (
    <>
      {addReftoFirstChild(children, testRef)}

      <button onClick={() => console.log(testRef.current)}>Test Ref!</button>
    </>
  );
}

function App() {
  return (
    <Wrapper>
      <img
        src='https://www.publicdomainpictures.net/pictures/80000/velka/odd-eyed-kitten.jpg'
        width={200}
        height={125}
      />
      <img
        src='https://c.files.bbci.co.uk/12A9B/production/_111434467_gettyimages-1143489763.jpg'
        width={200}
        height={125}
      />
    </Wrapper>
  );
}

Upvotes: 1

Related Questions