Posted on Jan 25, 2016 react node
Lets say you have a library of common react components, and that you’re using this library in some other project. If you have some unit tests in your project which use these library components, things work just fine when your project has installed your component library via
npm install - but lets say you want to use a local development copy of your components library and
npm link it to your parent project so you can make changes to the library easily. Now when you run your parent projects unit tests, you’ll probably see something nasty like this
Uncaught Error: Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. This usually means that you're trying to add a ref to a component that doesn't have an owner (that is, was not created inside of another component's `render` method). Try rendering this component inside of a new top-level component which will hold the ref.
The reason for this is that your components library, and your parent project both have thier own locally installed dependency on react, and when you load the unit tests your library components are using the copy of react from the component library, and your parent project is using its own copy of React. React doesn’t like it when you load multiple instances of it at once, and you’ll see the above error when you do. Usually when installed via
npm install, this isn’t a problem as the components library probably declares react as a peerDependency, and would rely on the parent projects copy - but when using a development copy using
npm link the component library probably has a copy of react installed locally as a devDependency, leading to duplicate copies of React and the problem described above.
After struggling with this issue, I found a workaround that doesn’t involve changing the library or parent project considerably, so I thought I’d post it here to help anyone who has this issue in future. Include this file before you require or import React and the error will magically go away. The easiest way I’ve found to include this is to have a single file index.js which exports all your libraries components, and in your package.json add the file below as loader.js and set it as the “main” file. This file should then, after patching the loader, require index.js. This way you don’t have to change any of your component code.
One caveat to note is that if you are building a distribution of your components library using webpack, you’ll have to conditionally exclude this code from running by using a conditional and the webpack DefinePlugin otherwise webpack builds will fail due to not being able to load the ‘module’ module.