remix-run/react-router

React.lazy makes Route's proptypes fail

Closed this issue Β· 28 comments

jgoux commented

Hello,

The newly introduced React.lazy for easy code-splitting is making the Route component proptypes to fail with the warning :

Warning: Failed prop type: Invalid prop `component` of type `object` supplied to `Route`, expected `function`.

Version

react-router-dom: 4.4.0-beta.4
react: 16.6.0

Test Case

I took the official example from here : https://reactjs.org/docs/code-splitting.html#route-based-code-splitting

https://codesandbox.io/s/xp2nwl2qxw

nfvs commented

Same thing with React.memo().

Likely fixed by #6327 and/or #6417.

Did you also upgrade react-dom to 16.6.0? I had the same issues but this tweet from @gaearon to a similar issue solved it for me.

edit: Never mind, I see the package.json now. The above fixed the issue for my case, but perhaps there is also something else going on.
edit2: I see, originally it was not rendering at all but now I still see the console errors. Ignore me πŸ˜“

So how exactly can I fix this warning? I'd read the #6417 and #6327 issues and saw the PR was merged into the master branch. Currently I'm on version 4.3.1 of react-router but still seeing this warning in the console. Thanks in advance!

Wait for a release :)

@rnnyrk I just did the following for now πŸ€·β€β™‚οΈ

const Home = React.lazy(() => import('./Home')

<Route exact path="/" component={props => <Home {...props} />} />

@tylerwray The trick doesn't seem to work with Typescript since Lazy doesn't have proper typing and jsx elements must be explicitly defined as a jsx component.

This was fixed in beta.5.

It's still an issue if react-is is resolved to 16.5.x - took me a good hour to track that down.

If you want, I can create a PR to bump the dependency requirement, perhaps?

Here's a reproduction, forked from the original codesandbox in this issue: https://codesandbox.io/s/q3y66owkj6

Ah, sorry!

@rnnyrk I just did the following for now πŸ€·β€β™‚οΈ

const Home = React.lazy(() => import('./Home')

<Route exact path="/" component={props => <Home {...props} />} />

This trick does fix the error, but can have some side effect since it makes Home component re-render at every parent render. ( eg: if Home have componentDidMount )

@pierreferry if you go that path, the render prop would be better.

@pshrmn hey,when will you publish 4.4.0 version,this is a common problem。

Any updates? It would be a great gift for the new year for me :)

Same here, any updates?

Same. The render prop work around resolves the warning. Not sure why this issue is closed though. It needs a fix. Β―\_(ツ)_/Β―

I resolve this warning by using render <Route exact path="/" render={() => <Home />} />

@willnew , as @pierreferry mentioned:
This trick does fix the error, but can have some side effect since it makes Home component re-render at every parent render. ( eg: if Home have componentDidMount )

@vtereshyn I believe this is different :

I haven't tested render method yet :)
Another thing i haven't tested: using not-inline functions

const renderHome = () => <Home />;

<Route exact path="/" render={renderHome} />

@vtereshyn I made a small Demo, you can test with it with Paint flashing option enabled on Chrome developer tool, the Home component didn't get re-rendered every time its parent's state change. so I think its a workaround, though it is a trick

@willnew , oh, sorry, misunderstood.
Okay, but its really a trick, so, I will wait for new release from react-router.

@vtereshyn it's OK, I made a mistake that I didn't explain in detail in my first comment.
For others who worry about the case which @pierreferry mentioned, you can edit the demo code by entering
<Route exact path="/" render={props => <Home {...props} />} />
and
<Route exact path="/" component={props => <Home {...props} />} />
to see the paint flashing zone

another option is to extend proptype definition for Route component prop (if not removed on build):

// react-router-dom-fix.js
import PropTypes from 'prop-types';
import { Route } from 'react-router-dom';

// suppress prop-types warning on Route component when using with React.lazy
// until react-router-dom@4.4.0 or higher version released
/* eslint-disable react/forbid-foreign-prop-types */
Route.propTypes.component = PropTypes.oneOfType([
  Route.propTypes.component,
  PropTypes.object,
]);
/* eslint-enable react/forbid-foreign-prop-types */

should not have any side effects...

I have the same in js code, but it not happen in ts.

another option is to extend proptype definition for Route component prop (if not removed on build):

// react-router-dom-fix.js
import PropTypes from 'prop-types';
import { Route } from 'react-router-dom';

// suppress prop-types warning on Route component when using with React.lazy
// until react-router-dom@4.4.0 or higher version released
/* eslint-disable react/forbid-foreign-prop-types */
Route.propTypes.component = PropTypes.oneOfType([
  Route.propTypes.component,
  PropTypes.object,
]);
/* eslint-enable react/forbid-foreign-prop-types */

should not have any side effects...

This works for me. is it trustable @sunstorymvp ?

@prakashtsi works as expected. waiting for new release which is compatible with React.lazy to get rid of this code

I just fixed it with updating react-dom to 16.6.3.
So before this the react version for my project is 16.6.3 and the react-dom version is 16.4.1. So I updated react-dom too.