React: Get class based components REF with lazy import

Created on 4 Apr 2019  路  17Comments  路  Source: facebook/react

Do you want to request a feature or report a bug?

  • Feature request

What is the current behavior?

  • Can't get components REF.

Issue is:

I have ComplexGrid that extends React.PureComponent.
I want to load this component dynamically.

React version = 16.8.5
Eg:

const ComplexGrid = React.lazy(() => import('@cc/grid/ComplexGrid'));

Then inside constructor I create this.gridRef = React.createRef();

Then JSX part:

<React.Suspense fallback={<div>Loading</div>}> <ComplexGrid ref={this.gridRef} {...some props here} /> </React.Suspense>

And then I get warning about React.forwardRef.
The problem:

  • My ComplexGrid component has some methods (UpdateColumnMetrics, ...etc)
  • I need ref to call these methods.
  • I don't need to forward ref to 'div' element (or others), I need component's instance
  • I need normal ref behavior, like with static imports

Is here any solution?

codesandbox example:

https://codesandbox.io/embed/ojkk2z5335

Needs Investigation

All 17 comments

image
This is the warning that I've got. Ref is not working.

P.S.
Tried to use '@loadable/component' - with this lib. Refs working.

Your codesandbox isn't producing any warnings for me. It works as you expected.

From your warning message I would infer that you imported a function component instead.

Here is the problem...

image

STGrid - class based component

class STGrid extends React.PureComponent { code.... } export default STGrid;

But when I open Popup, dynamic imports is triggering and I see warning...

Codesandbox code is the same (similar) like I use in my App. Just have no more ideas why this not working.

Maybe lazy() - function based wrapper component, or just async function... Then I have no idea how to use normal ref with dynamic imports

Codesandbox code is the same (similar) like I use in my App.

Well the codesandbox is not causing any warnings while your App does. You could try removing the lazy and see if you still get warnings. Otherwise it will be hard to help you without a minimal example.

Without lazy all works perfectly. No warnings.

Perhaps you could prepare a repository we can clone and try?

Perhaps you could prepare a repository we can clone and try?

Yes, I will try to prepare repo. It will take some time. Project is big, I will try to do small copy.

Perhaps you could prepare a repository we can clone and try?

Yes, I will try to prepare repo. It will take some time. Project is big, I will try to do small copy.

As I said, I prepared repo for tests. There is only 4 components.
App.jsx - here is main lazy imports
ComponentA, ComponentB, ComponentC - wrapped buttons.
I get the same warning. Maybe problem in node_modules, maybe in webpack config, maybe it is React bug.

Here is repo for tests:

ReactLazySuspenseRefBug repo

Server starts on: localhost:8080

Looks like an issue with react-hot-loader. It is patching components with a function wrapper in

https://github.com/gaearon/react-hot-loader/blob/5e6cc4b4b1867a8e563cb92d1e51ee6423ab6bf4/src/reconciler/fiberUpdater.js#L22-L27

If I use

React.forwardRef(function _default(props, ref) {
  return React__default.createElement(
    AppContainer,
    null,
    React__default.createElement(C, {...props, ref})
  );
})

instead I get no error.

I will work on a patch for react-hot-loader. Though react-hot-loader does support react^15 and react^16.0.0 so we need to find a good strategy.

Looks like an issue with react-hot-loader. It is patching components with a function wrapper in

Understood :) Probably for production (without react-hot-reload) all will be okay.

I will work on a patch for react-hot-loader.

Fortunately, I don't use refs with lazy import right now, just wanted to test this case.

Though react-hot-loader does support react^15 and react^16.0.0 so we need to find a good strategy.

Yes, supporting different versions is problematic work... Maybe possible to pass some configuration from webpack.config file, or get version from package.json, then conditional cases... Don't have any ideas...

Thank you for answer and help!

If I use

React.forwardRef(function _default(props, ref) {
  return React__default.createElement(
    AppContainer,
    null,
    React__default.createElement(C, {...props, ref})
  );
})

instead I get no error.

Tested this code part, all works perfectly.
Currently I can just copy-paste this part inside my 'node_modulesreact-hot-loader\distreact-hot-loader.development.js' until fix arrives.
But also I need to remove this alias from webpack configuration on production build
'react-dom': '@hot-loader/react-dom'
Simple :)

I guess this can be closed since gaearon/react-hot-loader#1221 was already merged. Thanks @theKashey for responding so quick.

Try [email protected]

I'll try it this monday. Guess everything will be okay :)

Try [email protected]

It's working :)

glad this is resolved! closing this

Was this page helpful?
0 / 5 - 0 ratings