3

I developed a React components library that I'm using from some of my projects.

One of them is a Storybook, so I created a BrowserRouter decorator to add to my stories and the components render perfectly just for showing and playing around purposes.

However, when using some of the components from another project, which has a BrowserRouter on the top level of my app components tree, I get this error:

Error: Invariant failed: You should not use <Link> outside a <Router>

Here, you can see a brief snippet of what I'm trying to render from my ConsumerProject:

index.js:


import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { LibraryComponent } from 'my-library';

const element = (
      <HotEnabler>
        <BrowserRouter>
          <RouterTrigger trigger={pathname => triggerHooks(_routes, pathname)}>
            <ApolloProvider client={client}>
              <ApolloProviderHooks client={client}>
                <LibraryComponent />
              </ApolloProviderHooks>
            </ApolloProvider>
          </RouterTrigger>
        </BrowserRouter>
      </HotEnabler>
);

ReactDOM.render(element, destinationDomElement);

Here, you can see the most important parts of MyLibrary:

package.json:

...
"peerDependencies": {
    "react": ">=16.8.6",
    "react-dom": ">=16.8.6",
    "react-router": ">=5.0.0",
    "react-router-dom": ">=5.0.0",
    "styled-components": ">=4.1.0"
}

libraryComponent.js:

import React from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';

import { SCLink } from './styles';

const LibraryComponent = props => {
  return (
      <Link
        to={'/any-route/'}
      >
        Testing Links
      </Link>
    );
  }
};

export default LibraryComponent;

I wanted to add something important:

If I add this alias to the Webpack config of ConsumerProject:

react: path.join(constants.ROOT_DIR, '../my-library/node_modules/react/'),
'react-dom': path.join(constants.ROOT_DIR, '../my-library/node_modules/react-dom/'),
'react-router-dom': path.join(constants.ROOT_DIR, 'node_modules/react-router-dom/')

Everything works fine. If I don't add them, I get errors both from React and from React Router Dom.

rmartrenado
  • 1,516
  • 1
  • 18
  • 42
  • This looks similar to https://stackoverflow.com/questions/56708153/export-react-router-redirect-from-shared-component-library so (like in my comment in that) can you create a sandbox that reproduces this problem? – apokryfos Jun 25 '19 at 09:30
  • I don't know how I could create a sandbox... consider that I have 2 projects, and I would need to publish somewhere the library... – rmartrenado Jun 25 '19 at 10:07
  • If you can't reproduce this when directly using the `LibraryComponent` but can reproduce this when using `LibraryComponent` as an external library then perhaps there's an issue with the packaging of the 3rd party library. This is further supported by the fact that you had to hack your way around the webpack config. It is possible this is an [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) – apokryfos Jun 25 '19 at 10:08
  • @rmartrenado Did you ever find a solution to this? I am running into a similar problem – Nabeel Mehmood Oct 01 '20 at 09:20
  • We can probably chat about this, I could share some config with you.. How can we start a chat here? – rmartrenado Oct 02 '20 at 10:15
  • @rmartrenado could you please share your solution as an answer here? that would be very helpful – Borys Kupar Nov 03 '20 at 17:58

1 Answers1

3

I had the same problem with my library that had components depending on react-route-dom. After some investigation, I came to the conclusion that in my project app, there are 2 versions of react-router-dom bundled (even the same version), which creates 2 Context instances that conflict with each other.

The solution in my case was to move react-router-dom to peerDependencies, and exclude it from library build with webpack configuration:

externals: {
  'react-router-dom': {
    root: 'ReactRouterDom',
    commonjs2: 'react-router-dom',
    commonjs: 'react-router-dom',
    amd: 'react-router-dom',
  },
},

More in-depth information was found here.

Borys Kupar
  • 1,631
  • 11
  • 24