Why should I install libraries A(react-router) and B (react-router-dom) when the library B depends on A?

I am now trying to figure out why it is necessary to specify all the dependencies explicitly in the packages.json file.

For example: I want to use the react-router library. The official documentation says:

npm install react-router@6 react-router-dom@6

This means that to work with this library, I need to install (and maintain/update) two packages. Of course, there is no problem updating two packages, but when there are many such packages, it looks strange.

Also, the official documentation says:

you should never import anything directly from the react-router package, but you should have everything you need in either react-router-dom

I’m trying to figure it out further and I look at how the packages.json file works for the react-router-dom library and i see

"dependencies": {
  "react-router": "6.0.0-beta.1"
},

For me, this means that if I install the react-router-dom library, it will automatically pull up the dependencies that are specified in the dependencies section, so react-router should be installed automatically and I should not explicitly install it in my project.

So in general why or what benefits/best practices of install libs like npm install react-router@6 react-router-dom@6 instead of npm install react-router-dom@6?

Answer

Ok, lets shed some light on this.

react-router-dom and react-router-native both are based on react-router. They extend functionality with specific features and components for each environment. They have react-router as a direct dependency and they re-export every object from it.

So, you DON’T need to explicitly add react-router to your own package.json dependencies if you are using react-router-dom or react-router-native packages. Regardless of what the “Migrating React Router v5 to v6” Guide says.

However, there are some special cases and the only thing that you wan’t to avoid is to have multiple versions of the same packages (because this will increase bundle size) and to have multiple instances of something where there should be only one (this is important with react-router and this is why the documentation encourages you to add it as a peer dependency in the case that you really have to access it directly. It can be!).

I think this is why the migration guide installs both. It may be assuming those special cases where you are using both packages (instead of using peer dependencies they just fix both versions using @6 syntax. Most likely react-router-dom@6 and react-router-native@6 both have react-router@6 as a direct dependency. If not, above described problems could be encountered.)

In conclusion, if you are not explicitly importing from react-router DO NOT add it to your package.json.

Also remember that there is not a definitive rule and that your package manager is designed to resolve redundancy and optimize dependencies. Explicit dependencies declarations are generally better than implicit dependencies usage. You just have to be sure to be coherent and to not fall in the above described cases.