I have a component library package where I own some components that I want to render into an app owned by a different team. I would like to be able to use stuff like <Route />
and <Link />
in my components package but I get an error like Uncaught Error: Invariant failed: You should not use <Link> outside a <Router>
when I try to do so.
The app in which I am rendering my components into has react router already set up and working. It renders a <BrowserRouter />
near the top level as per usual. When trying to use Link
or Route
from any file within the app itself, it works fine. It just seems that I can't import router stuff from outside it and use it.
This does not work:
/* MyExternalComponent.js (this is in my external package) */
import React from 'react';
import { Link } from 'react-router-dom';
const MyExternalPackage = () => (
<Link to="/about">About</Link> // This throws the "Invariant failed" error
);
/* SomePage.js (this is in the actual app) */
import React from 'react';
import { MyExternalComponent } from 'my-external-package';
const SomePage = () => (
<MyExternalComponent />
);
However, this DOES work:
/* MyExternalComponent.js (this is in my external package) */
import React from 'react';
const MyExternalPackage = ({ children }) => (
<h1>hi</h1>
);
/* SomePage.js (this is in the actual app) */
import React from 'react';
import { Link } from 'react-router-dom';
import { MyExternalComponent } from 'my-external-package';
const SomePage = () => (
<MyExternalComponent />
<Link to="/about" /> // I can render the link from the same context where I am rendering my component...
);
This also works:
/* MyExternalComponent.js (this is in my external package) */
import React from 'react';
const MyExternalPackage = ({ children }) => (
{children} // Renders a link that routes me to /about
);
/* SomePage.js (this is in the actual app) */
import React from 'react';
import { Link } from 'react-router-dom';
import { MyExternalComponent } from 'my-external-package';
const SomePage = () => (
<MyExternalComponent>
<Link to="/about" />
</MyExternalComponent>
);
It seems for whatever reason that this issue only happens when I import Route
or Link
from within my package. When I render them as children of my component, everything works fine. I'm not sure why this is happening as it is clear that routing works within the app itself and I am rendering my component in a place where <Link />
works fine.
Any suggestions/tips would be greatly appreciated!
To resolve issues like this where React/React Router end up having multiple instances in the consumer/dependency package due to npm link
, you can add something like this in your webpack.config.js
:
resolve: {
alias: {
react: path.resolve('./node_modules/react'),
'react-router': path.resolve('./node_modules/react-router'),
'react-router-dom': path.resolve('./node_modules/react-router-dom')
}
},
This will ensure that only the consumer's version of React/React Router is used in both places.
Original text:
It turns out that the issue was because of how I was doing local development by using npm link
in my components package + npm link my-external-package
from the App. I'm guessing there is some node_modules
issue happening because of this link..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With