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.

6
  • This looks similar to stackoverflow.com/questions/56708153/… so (like in my comment in that) can you create a sandbox that reproduces this problem? Commented Jun 25, 2019 at 9: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... Commented Jun 25, 2019 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 Commented Jun 25, 2019 at 10:08
  • @rmartrenado Did you ever find a solution to this? I am running into a similar problem Commented Oct 1, 2020 at 9:20
  • We can probably chat about this, I could share some config with you.. How can we start a chat here? Commented Oct 2, 2020 at 10:15

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.