Как избежать "загрузки двух копий ошибки React" при разработке внешнего компонента?
Я разрабатываю внешний компонент (скажем, my-component
, который я связываю с проектом с npm link
(как он находится в процессе, и мне нужен пакет для отражения изменений).
В папке my-component
есть node_modules/react
и node_modules/react-dom
, поскольку они являются его зависимостями. Однако они являются peerDependences, поэтому я не предполагал привести их в проект, связывающий этот пакет.
Однако при использовании npm link
он связывает весь каталог, включая node_modules
. Итак, когда проект строится, он включает пакеты 2 раза: от node_modules/*
и от node_modules/my-component/node_modules/*
.
Это начинает влиять, когда компонент использует ReactDOM.findDOMNode
, он вызывает эту ошибку:
Warning: React can't find the root component node for data-reactid value `.0.2.0`. If you're seeing this message, it probably means that you've loaded two copies of React on the page. At this time, only a single copy of React can be loaded at a time.
Кроме того, это может помочь понять, что происходит: проблема возникает только в том случае, если есть как node_modules/my-component/node_modules/react
, так и node_modules/my-component/node_modules/react-dom
. Если есть только один из них, сообщение об ошибке отсутствует.
Обычная установка пакета не приводит к такой ошибке, поскольку там нет node_modules/react-dom
.
Как предполагается создание внешнего компонента и проекта в одно и то же время?
Ответы
Ответ 1
Я считаю, что ответ заключается в том, чтобы указать react
и react-dom
как peerDependencies
в вашем внешнем компоненте package.json
. Насколько я могу следовать здесь и здесь, npm link
должен (начиная с [email protected]
) больше не устанавливать peerDependencies
(или `devDependencies).
Aaaand Я просто внимательно прочитал ваш пост и понял, что вы уже указываете их как peerDependencies
. Поэтому я думаю, что ответ сводится к следующему:
Обновить до [email protected]
:
npm install -g [email protected]
Ответ 2
Кто-то умнее меня (@mojodna) придумал это решение: удалите дубликаты зависимостей от внешнего компонента и разрешите их с вашими проектными копиями этих депок.
Шаг 1: Удалите зависимости от вашего внешнего компонента node_modules
Как @cleong отметил, вы не можете просто удалить отпечатки из внешнего компонента node_modules
, потому что ваш шаг построения проекта не удастся, когда он ударит -изменение зависимостей во внешней компоненте.
Шаг 2. Добавьте проект node_modules
в NODE_PATH
Чтобы исправить это, вы можете добавить проект node_modules
к переменной среды NODE_PATH
при запуске шага сборки. Что-то вроде, например, это:
NODE_PATH=$(pwd)/node_modules/ npm start
(где npm start
- ваш script, который связывает ваш внешний компонент, например, с помощью браузера, Webpack и т.д.)
На самом деле вы всегда можете добавить дополнение NODE_PATH
к вашим скриптам сборки, и оно будет работать независимо от того, есть ли у вас npm link
что-нибудь. (Заставляет меня задаться вопросом, не должно ли это быть поведение по умолчанию npm
...)
Примечание. Я оставил свой существующий ответ, потому что там какой-то разговор, и это другое (и лучшее) решение.
Ответ 3
Исправлено, добавив react-dom
в качестве псевдонима в мою конфигурацию webpack
alias: {
react$: require.resolve(path.join(constants.NODE_MODULES_DIR, 'react')),
'react-dom': require.resolve(path.join(constants.NODE_MODULES_DIR, 'react-dom'))
}
Ответ 4
Проблема двоякая:
- У вас не может быть загружено 2 копии реакции.
- npm link создает символическую ссылку, однако "require" не уважает
symlink, и когда он пытается перейти по каталогу, он никогда
находит реакцию родительского проекта.
Решение:
Все, что вам нужно сделать, это связать реакцию и реакцию с вашим компонентом с компонентом родительского проекта node_modules.
Перейдите к проекту компонента и удалите реакцию и реакцию, затем выполните
npm link ../myproject/node_modules/react
npm link ../myproject/node_modules/react-dom
Ответ 5
Проблема заключается в связи с npm. https://github.com/npm/npm/issues/5875
npm не обрабатывает связанный каталог как дочерний элемент родительского проекта.
Попробуйте альтернативы npm-ссылке:
1) Используйте относительные зависимости пути в package.json
2) Вручную укажите свои зависимости в своих проектах node_modules
3) Используйте URL-адрес пути
В принципе ничего, кроме ссылки npm
Ответ 6
Добавление следующего в мой webpack.config.js
сработало для меня:
resolve: {
alias: {
react: path.resolve(__dirname, 'node_modules', 'react')
}
}
Я также экспериментировал с DedupePlugin
(упоминался как возможное средство здесь), но я не мог заставить его работать.
Интересно также, что я столкнулся с различными (и, возможно, более коварными) проявлениями одной и той же проблемы, когда модуль найден в нескольких местах в графике зависимостей.
Один из таких случаев заключался в том, что мои ограничения React.PropTypes.instanceOf(SomeType)
выдавали бы предупреждения, даже если тип, который я прошел, был правильным. Это связано с тем, что модуль присутствует в нескольких местах в дереве каталогов node_modules
. Из-за утка-ввода код все равно будет работать, но моя консоль была загромождена этими предупреждениями. Переход к resolve.alias
тоже заставил их замолчать.
YMMV
Ответ 7
Если вы используете Webpack в основном проекте, это решение может работать. В моем случае project-a
требуется project-b
. Оба требуют React и ReactDOM 0.14.x
У меня это в project-a/webpack.config.js
:
resolve: {
modulesDirectories: ['node_modules'],
fallback: path.join(__dirname, 'node_modules')
},
resolveLoader: {
fallback: path.join(__dirname, 'node_modules')
},
-
project-b
требует React и ReactDOM как peerDependencies
в project-b/package.json
-
project-a
требует project-b
как devDependency
(также должен работать как dependency
) в project-a/package.json
- local
project-b
связан с project-a
следующим образом: cd project-a; npm link ../project-b
Теперь, когда я запускаю npm run build
внутри project-b
, изменения отображаются сразу же в project-a
Ответ 8
Я использую ReactJS.net и настраиваю webpack из учебника и начинаю использовать react-bootstrap
, когда я начал получать эту ошибку. Я обнаружил, что добавление 'react-dom': 'ReactDOM'
в список externals
в webpack.config.js
устраняет проблему, тогда список внешних выглядит следующим образом:
externals: {
// Use external version of React (from CDN for client-side, or
// bundled with ReactJS.NET for server-side)
react: 'React',
'react-dom': 'ReactDOM'
Это, похоже, первая ссылка в google для этой ошибки, поэтому я подумал, что этот ответ может помочь кому-то здесь.
Ответ 9
Я получал это, потому что уже включил react
и react-dom
в качестве внешних скриптов в моей разметке HTML.
Ошибка вызвана добавлением import ReactDOM from 'react-dom'
к компонентному модулю. Ошибка исчезла, как только я удалил импорт, и модуль работал нормально, поскольку компоненты уже были доступны.