2

I'm passing the ref using React.forwardRef to the down component which usually works.

<SomeComponent
component={React.forwardRef((props, ref) => <MyComponent innerRef={ref} {...props} />)}
.../>

However when I have HOC (higher order component) withStyles, the innerRef along with other props do not get passed properly.

// innerRef does not exists in props
const MyComponent = withStyles(styles)(({ one, two, ...props }) => {
    return (
        <Fragment>
            <NavLink {...props}></NavLink>
              ...
        </Fragment>
    );
})

Without using withStyles I get them perfectly

// innerRef exists in props
const MyComponent = ({ one, two, ...props }) => {
    return (
        <Fragment>
            <NavLink {...props}></NavLink>
              ...
        </Fragment>
    );
}

How can I still have the withStyles HOC but with innerRef and other props included?

The issue appeared after migration from material ui v3 to v4. NavLink requires the innerRef property.

EugenSunic
  • 13,162
  • 13
  • 64
  • 86
  • Would you mind checking if you call it something other than `innerRef`, does it get passed through? Do the other properties get passed down? – TKoL Sep 10 '20 at 16:03
  • yes, everything else gets passed down apart from the innerRef, is there some kind forwaredRef:true for withStyles? – EugenSunic Sep 10 '20 at 16:04
  • I suspect innerRef is being captured by `withStyles`, but you can pass it down as another prop, `nRef`, and then inside MyComponent, before you return your render, do `props.innerRef = props.nRef;` – TKoL Sep 10 '20 at 16:05
  • https://github.com/mui-org/material-ui/pull/9765 -- this suggests to me that I might be right, `innerRef` is being used by material ui / withStyles, so just pass it down with a different name and then change the name in the render function when you need it. – TKoL Sep 10 '20 at 16:08
  • Question edited, not of the props inside React.forward are passed to MyComponent – EugenSunic Sep 10 '20 at 16:38
  • @EugenSunic You may have multiple problems confusing the issue. You shouldn't use `React.forwardRef` inline. Instead use it at the top-level as part of your component definition; otherwise on every re-render you will be passing a new component type to the `component` prop which will cause a number of confusing problems. – Ryan Cogswell Sep 10 '20 at 17:18
  • @EugenSunic Looking more carefully at your example, you shouldn't need `forwardRef` at all. `MyComponent` just needs to use the `ref` directly (as in my answer). – Ryan Cogswell Sep 10 '20 at 17:23
  • @EugenSunic If you do still think you need `forwardRef`, please create a [code sandbox](https://codesandbox.io/s/new) reproducing your problem. – Ryan Cogswell Sep 10 '20 at 17:24

2 Answers2

2

withStyles passes along innerRef as ref, so something like the following should work:

const MyComponent = withStyles(styles)(({ one, two, ...props }, ref) => {
    return (
        <Fragment>
            <NavLink {...props} ref={ref}></NavLink>
              ...
        </Fragment>
    );
})

Or if you need to keep it as innerRef on NavLink:

const MyComponent = withStyles(styles)(({ one, two, ...props }, ref) => {
    return (
        <Fragment>
            <NavLink {...props} innerRef={ref}></NavLink>
              ...
        </Fragment>
    );
})
Ryan Cogswell
  • 75,046
  • 9
  • 218
  • 198
  • I do not get the ref passed, just searched for it... – EugenSunic Sep 10 '20 at 17:37
  • 1
    Searched for it how? It isn't a prop -- it's the second argument to the component after `props`. – Ryan Cogswell Sep 10 '20 at 17:38
  • @EugenSunic As I indicated in the comments on your question, please create a code sandbox reproducing the problem. – Ryan Cogswell Sep 10 '20 at 17:40
  • sorry for that, yes after providing a second argument I still do not get it, get some errors, will try and create a stackblitz later.. tnx for the help... – EugenSunic Sep 10 '20 at 17:46
  • @RyanCogswell you say it isn't a prop, but the code you linked to certainly looks like it's passing `ref` as a prop: `return ;` – TKoL Sep 11 '20 at 08:09
  • @TKoL The jsx syntax for specifying `ref` is the same as props, but `ref` (and `key`) are treated differently by React. Neither `ref` nor `key` are included in the props object that is passed to the component. – Ryan Cogswell Sep 11 '20 at 12:59
0

My recommendation based on my comments:

<SomeComponent
component={React.forwardRef((props, ref) => <MyComponent nRef={ref} {...props} />)}
.../>
const MyComponent = withStyles(styles)(({ one, two, ...props }) => {
    props.innerRef = nRef;
    return (
        <Fragment>
            <NavLink {...props}></NavLink>
              ...
        </Fragment>
    );
})

Or alternatively

<NavLink {...props} innerRef={props.nRef}></NavLink>

TKoL
  • 13,158
  • 3
  • 39
  • 73