Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Router Invariant failed when Route or Link is used in an external package

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.


To Summarize

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!

like image 655
Saad Avatar asked Oct 20 '25 03:10

Saad


1 Answers

EDIT

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..

like image 70
Saad Avatar answered Oct 21 '25 19:10

Saad