0

I'm trying a very simple test to understand component references in Next.js, but no matter what I do, current is always undefined.

Here's the setup (on a blank Next.js application): components/test.tsx

import {MouseEventHandler, ReactNode, RefAttributes} from "react";

interface TestProps {
    onClick?: MouseEventHandler
}
export default function TestComp({ ...props }:TestProps & RefAttributes<unknown>) {
    return (
        <div onClick={props.onClick?props.onClick:undefined}>Test</div>
    )
}

And then we have pages/index.tsx

import React, {createRef, forwardRef, useRef} from "react";
import TestComp from "../components/test";

// eslint-disable-next-line react/display-name
const TestWrapper = forwardRef((props: any, myref) => (
    <TestComp{...props} ref={myref} />
));

const Home: NextPage = () => {
  const el = useRef(null);
  function testRef() {
    console.log(el.current);
  }
  return (
      <TestWrapper
          myref={el}
        onClick={testRef}
      />
  );
};

Tried with useRef, createRef - nothing seems to work. el.current is always null or undefined. What am I doing wrong?

Thanks!

(This is with "next": "12.1.6", "react": "18.2.0", "react-dom": "18.2.0", FWIW )

Update Replacing "myref" with "ref" doesn't work either (complains that functional components can't have references)

Alexander
  • 21
  • 3
  • Well, you aren't passing any `ref` prop to `TestWrapper`, and even if it was passed correctly `TestWrapper` doesn't attach the ref to a DOMNode or set the current value to anything, so `el.current` will still be `null`. What are you trying to accomplish with this code/ref? – Drew Reese Aug 19 '22 at 05:24
  • I'm not sure what you mean. The property is called myref in TestWrapper, so that's what I'm passing - the one that matters is the one in TestComp. The assignment should happen automatically by the library, I shouldn't be doing it explicitly. ( https://reactjs.org/docs/forwarding-refs.html ) – Alexander Aug 19 '22 at 05:55
  • `myRef` is just a regular old React prop, nothing special. If you pass a *special* `ref` prop to `TestWrapper`, i.e. ``, then the `forwardRef` will forward it and it will be named `myRef` in `TestWrapper`. And then as I said, the code still needs to do *something* with the ref to give it a current value. This is why I asked what you are trying to accomplish with the ref usage. What does `TestComp` need to do with the ref? – Drew Reese Aug 19 '22 at 05:59
  • Exactly, myRef is a regular prop - nothing special. It just carries its assigned value (el) to the wrappping component where that value *is* assigned to the special "ref" property. You can't assign ref directly to TestWrapper because refs cannot be assigned to functional components - which is the reason for using forwardRef in the first place. My understanding is that it's the library that assigns the ref.current value, not my code. Here's another example: https://stackoverflow.com/questions/66664209/how-can-i-use-forwardref-in-react – Alexander Aug 19 '22 at 06:05
  • No, a passed `ref` prop will be forwarded and named `myRef` and passed to `TestComp`'s `ref` prop. The `myRef` prop you passed to `TestWrapper` is accessible on `props.myRef` and is never referenced in `TestComp` (*well, it's passed long in `{ ...props }`*). Do you see the difference? If you could just explain what you are trying to accomplish overall we could probably provide an answer with a correctly passed/forwarded React ref. – Drew Reese Aug 19 '22 at 06:07
  • I'm not following your suggestion. Trying to pass ref directly, as in always gives an error - functional components can't have refs. – Alexander Aug 19 '22 at 06:15
  • I don't really know what to say to that. The code examples in [forwarding refs](https://reactjs.org/docs/forwarding-refs.html) are function components, and the in the other [SO post](/questions/66664209/how-can-i-use-forwardref-in-react) function components are also used. That is what `forwardRef` is for, passing refs to function components. If you don't want to explain your goal here that's fine, but I've already explained why the refs aren't working in your code, just trying to get you to working code. – Drew Reese Aug 19 '22 at 06:19
  • To be more specific, this doesn't work either: ``` const TestWrapper = forwardRef((props: any, ref) => ( ... ``` "Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?" My goal is simply accessing the component from events, to use some of its properties and methods. – Alexander Aug 19 '22 at 06:22
  • Maybe try wrapping *all* the function components with `forwardRef` that you are trying to pass a React ref to. – Drew Reese Aug 19 '22 at 06:23
  • The problem is that I reach a point where the components I refer to are no longer under my control. I ended up rewriting the code as a class components. Too much acrobatics for such a simple task (getting a reference to myself). The idea was simply having a reference to those components (not under my control) so that I can use them in events and manipulate their properties and state. – Alexander Aug 19 '22 at 06:57
  • I'd imagine these other components either do, or do not, take a React ref. How the ref gets there is up to you. You should be able to forward the refs, or just pass them through your components as a regular named prop until you need to *actually* pass it as `ref`. – Drew Reese Aug 19 '22 at 07:00

0 Answers0