Estoy desarrollando un módulo React localmente. Para eso, estoy vinculando mi módulo usando npm link
. El módulo se importó con éxito, pero los ganchos fallan dentro del módulo. Está lanzando el siguiente error:
Llamada de gancho no válida. Los ganchos solo se pueden llamar dentro del cuerpo de un componente de función. Esto podría suceder por una de las siguientes razones: 1. Es posible que tenga versiones que no coincidan de React y el renderizador (como React DOM) 2. Es posible que esté infringiendo las Reglas de Hooks 3. Es posible que tenga más de una copia de React en la misma aplicación Consulte https://reactjs.org/link/invalid-hook-call para obtener consejos sobre cómo depurar y solucionar este problema.
Al revisar las sugerencias en React docs , puedo confirmar que mi aplicación está usando versiones duplicadas de React ya que el siguiente código devuelve falso:
// node_modules/mymodule/src/index.js export { default as ReactFromModule } from 'react'
// src/index.js import React from 'react' import { ReactFromModule } from 'mymodule' console.log(React === ReactFromModule) //false
Este número está lleno de sugerencias, pero son confusas. ¿Cómo puedo resolverlo?
Nota: no estoy rompiendo las reglas de los ganchos, el error aparece solo al importar el módulo desde una aplicación.
En el módulo que está desarrollando, agregue los paquetes en conflicto a peerDependencies
(y elimínelos de las dependencies
o devDependencies
):
// package.json "peerDependencies": { "react": "16.13.1", "react-dom": "16.13.1" },
Ejecute npm install
en su módulo.
Ahora agréguelos a la configuración del paquete web de su módulo como externals
. Estos paquetes no deben incluirse en el paquete del módulo (la aplicación que usa el módulo los proporcionará):
// webpack.config.js module.exports = { /* rest of config... */ output: { filename: "index.js", pathinfo: false, libraryTarget: 'umd', // In my case, I use libraryTarget as 'umd'. Not sure if relevant }, externals: { // Use external version of React "react": { "commonjs": "react", "commonjs2": "react", "amd": "react", "root": "React" }, "react-dom": { "commonjs": "react-dom", "commonjs2": "react-dom", "amd": "react-dom", "root": "ReactDOM" } }, };
Luego, después de construir su módulo, en su aplicación puede verificar que ambas versiones ahora son iguales:
// node_modules/mymodule/src/index.js export { default as ReactFromModule } from 'react'
// src/index.js import React from 'react' import { ReactFromModule } from 'mymodule' console.log(React === ReactFromModule) // true :)
En respuesta a otro comentario, simplemente mover React a peerDependencies no resuelve adecuadamente el problema en todos los casos. Respondería a ese comentario directamente, pero StackOverflow requiere más reputación para responder a las respuestas incorrectas que para publicarlas.
Tengo un módulo de componente React compartido creado con Webpack y me he encontrado con el mismo problema. He esbozado una posible solución en este comentario a continuación que requiere modificar peerDependencies y usar el enlace npm de una manera similar a la respuesta compartida por mtkopone. https://github.com/facebook/react/issues/13991#issuecomment-841509933
Mi solución es un poco complicada y no la recomendaría para uso a largo plazo. Si está utilizando Webpack (que marcó esta pregunta), este artículo puede detallar una solución más permanente ( https://medium.com/codex/duplicate-copy-of-react-errors-when-using-npm-link -e5011de0995d ). Todavía no lo he probado, pero el autor parece haber probado todas las soluciones (incorrectas) que existen y también se encuentra con el problema de los ganchos al intentar crear bibliotecas de componentes compartidos.
El autor de ese artículo está tratando de depurar una aplicación Create-React-App. Si bien CRA usa webpack bajo el capó, no puede acceder directamente a webpack.config, por lo que el autor tiene que realizar algunas soluciones para hacerlo. Si no está utilizando CRA, sino simplemente Webpack, entonces podría considerar usar la sección resolve.alias de webpack.config para asegurarse de que no haya copias duplicadas de React (ver: https://blog.maximeheckel.com/posts /duplicar-dependencias-npm-enlace/ )
Agregar react
y react-dom
como peerDependencies
en el package.json
no funcionó para mí.
Tuve que agregar un alias al archivo de configuración del paquete web:
// webpack.config.js resolve: { alias: { react: path.resolve('./node_modules/react'), }
Estaba intentando usar las dependencias de peerDependencies
y la eliminación de las devDependencies
de desarrollo y estaba fallando.
Resultó que tenía una carpeta node_modules
en una de las carpetas principales de la biblioteca en la que estaba trabajando y la versión duplicada de React se estaba cargando desde allí en lugar de la herramienta que intentaba usar la biblioteca React.
En lugar de editar las devDependencies
para eliminar la reacción, solo escribí un pequeño script para eliminar cualquier cosa que esté en las peerDependencies
de la carpeta node_modules
.
npm view --json=true . peerDependencies | jq -r 'keys | .[] | @text' | while read dep; do rm -r ./node_modules/${dep} && echo Removed ${dep}; done