skip to Main Content

I am trying to use a useRef between 2 components which are not directly linked.

How?

Since useRef is a hook, I cant just add this to some file and share it.

export const someRef = React.useRef(); // not possible, it needs to be inside a jsx component

I am trying to find a way to use it globally similar to how this would have been possible if this was state.

I’d have just used existing Redux implementation or context if this was state.

Please advice how to do the same for useRef. I don’t own Compo2 component below thus I need to stick with a ref here.

P.S: I could achieve this with some prop drilling going 6 levels down.. Trying not to do that.

// place reference on this component
export const Compo1 = () => {
  return (
    <div ref={someRef}>
      text 1
    </div>
  );
};


// same  someRef reference passed as a prop here from some other component which doesn't talk to Compo1. 
export const Compo2 = ({
  someRef,  
}) => {
  // Do something with the reference value
  return (
    <div>
      text 2
    </div>
  );
};

3

Answers


  1. In addition to object refs (an object with current prop), refs also accept functions (ref callback functions). A function ref (like setRef) is passed the ref to the element when called.

    Instead of useRef, you can use useState instead, get the ref using the setter function, and set it as the state. You can then pass the state to another component.

    You can use a parent component in this way, or use context.

    For example:

    // place reference on this component
    export const Compo1 = ({ setRef }) => {
      return (
        <div ref={setRef}>
          text 1
        </div>
      );
    };
    
    
    // same  someRef reference passed as a prop here from some other component which doesn't talk to Compo1. 
    export const Compo2 = ({ someRef }) => {
      // Do something with the reference value
      return (
        <div>
          text 2
        </div>
      );
    };
    
    const Parent = () => {
      const [ref, setRef] = useState();
    
      return (
        <>
          <Compo1 setRef={setRef} />
          <Compo2 someRef={ref} />
        </>
      );
    };
    
    Login or Signup to reply.
  2. To create ref in another file and use it in two different components which are not linked with each other you can use createRef

    App.js

    import { refs } from "./constant";
    
    export default function App() {
      return (
        <div ref={refs} className="App">
          <h1>Hello CodeSandbox</h1>
          <h2>Start editing to see some magic happen!</h2>
        </div>
      );
    }
    
    
    

    Comp1.js

    import { refs } from "./constant";
    
    export default function Comp1() {
      return <button onClick={() => console.log(refs)}>button</button>;
    }
    
    

    constant.js

    import React from "react";
    
    export const refs = React.createRef();
    
    

    index.js

    import { StrictMode } from "react";
    import { createRoot } from "react-dom/client";
    
    import App from "./App";
    import Comp1 from "./Comp1";
    
    const rootElement = document.getElementById("root");
    const root = createRoot(rootElement);
    
    root.render(
      <StrictMode>
        <App />
        <Comp1 />
      </StrictMode>
    );
    
    
    Login or Signup to reply.
  3. You could create a new global variable, for example:

    export const inputRef = { current: null };
    
    function Input() {
      return (
        <label>
          <input type="text" ref={inputRef} placeholder="Type something" />
        </label>
      );
    }
    export default Input;
    

    And then you can use it like you normally would, by importing.o

    import Input, { inputRef } from "./Input";
    
    function Container({ children }) {
      function handleClick() {
        inputRef.current.focus();
      }
    
      return (
        <div
          onClick={handleClick}
          style={{
            padding: 16,
            backgroundColor: "yellow",
          }}
        >
          {children}
        </div>
      );
    }
    
    export default function App() {
      return (
        <Container>
          <Input />
        </Container>
      );
    }
    

    See here a live version

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search