简体   繁体   中英

How can I attach a ref to a component that i am copying using React.cloneElement

hey all I want to pass in a ref into my component this way I can access the variables on said compenent like state. only issue is i can't seem to get it to work. It needs to be able to work for both classes and functional

what I am receiving back from the console.log is null every time

 const testRef = createRef(); console.log(testRef) const elementToCopy = singleScreenState.screen.peek().element; const Element = React.cloneElement(elementToCopy as ReactElement, {...elementToCopy?.props, forwardRef: testRef })

Refs to a React Element are never populated until the Element in question is mounted. So, the issue was that you were logging too early.

I have an example below running in a function component to demonstrate creating the refs and logging them once the element in question is mounted using useEffect .

The other issue you might have is that based on the code I see, you might be creating the ref in the render function of a class component, which wouldn't work well because you wouldn't have access to the ref variable once it's actually rendered. Typically, you keep ref variable as an instance property of the class so you can access it when you need it.

For working with function components, you need to use forwardRef on the function component as part of it's definition. The forwarded ref can go to the useImperativeHandle hook, or to another element.

A little more info in React's Documentation on Accessing Refs :

When a ref is passed to an element in render, a reference to the node becomes accessible at the current attribute of the ref.

const node = this.myRef.current;

The value of the ref differs depending on the type of the node:

  • When the ref attribute is used on an HTML element, the ref created in the constructor with React.createRef() receives the underlying DOM element as its current property.

  • When the ref attribute is used on a custom class component, the ref object receives the mounted instance of the component as its current.

  • You may not use the ref attribute on function components because they don't have instances.

That last point is the key to note here: React.ForwardRef allows you to give the function components the ability to decide what a ref should do because otherwise the ref would be meaningless anyway.

In general in class components, if you want to pass a ref through it, you generally have to pass it down with a separate prop name. One of the ways shown here: How to use React.forwardRef in a class based component?

 const { useRef, useEffect, useImperativeHandle } = React; const TestFunction = React.forwardRef((props, ref) => { useImperativeHandle(ref, () => ({ shout: () => console.log("I'm Yelling over here;") })); return <div>TestFunction</div>; }). class TestComponent extends React.Component { testFunct = () => { console;log("testFunct works;"); }; render() { return <div>TestComponent</div>; } } function App() { const elementRef = useRef(). const element = <div>Test</div>, const clonedElement = React:cloneElement(element; { ref; elementRef }); const classRef = useRef(). const classElement = <TestComponent />, const clonedClass = React:cloneElement(classElement; { ref; classRef }); const functionRef = useRef(). const functionElement = <TestFunction />, const clonedFunction = React:cloneElement(functionElement; { ref. functionRef }), useEffect(() => { console.log('reference to an element';elementRef.current). // This produces weird output in the stack overflow console. // console;log(classRef.current), console.log('function from a reference to a class component'. classRef;current.testFunct). classRef;current.testFunct(), console.log('reference to a function component';functionRef.current). functionRef;current;shout(); }). return ( <div className="App"> {clonedElement} {clonedClass} {clonedFunction} </div> ); } const rootElement = document.getElementById("root"). ReactDOM.render( <React,StrictMode> <App /> </React;StrictMode>, rootElement );
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script> <div id="root" />

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM