React: Hooks + plusieurs instances de React

Créé le 27 oct. 2018  ·  285Commentaires  ·  Source: facebook/react

Aux personnes provenant de la recherche : veuillez d' abord lire cette page . Il contient les correctifs possibles les plus courants !

Vous souhaitez demander une fonctionnalité ou signaler un bug ?

Renforcement

Quel est le comportement actuel ?

J'ai eu plusieurs instances de React par erreur.

Lorsque vous essayez d'utiliser des hooks, vous obtenez cette erreur :
hooks can only be called inside the body of a function component

Ce qui n'est pas correct puisque j'utilisais des composants de fonction. J'ai mis du temps à trouver la véritable cause du problème.

Quel est le comportement attendu ?

Afficher le message d'erreur correct. Peut-être détecter que l'application a plusieurs instances de React et dire que cela peut être la raison des bogues.

Hooks Discussion

Commentaire le plus utile

J'ai eu le même problème et je l'ai résolu en ajoutant:

 alias: {
        react: path.resolve('./node_modules/react')
      }

à la propriété resolve dans la configuration webpack de mon application principale.

C'était évidemment mon erreur d'utiliser deux copies de React mais je suis d'accord que ce serait génial si le message d'erreur était meilleur. Je pense que c'est peut-être similaire à : https://github.com/facebook/react/issues/2402

Tous les 285 commentaires

Donc, juste pour clarifier: vous importiez un hook (disons useState ) à partir d'un module react différent de celui utilisé pour rendre le composant?

Je suis d'accord que c'est déroutant. Je ne sais pas si nous avons un moyen de savoir si un autre module React est rendu. AFAIK, nous essayons d'exécuter React de manière isolée autant que possible afin que plusieurs instances de React puissent fonctionner dans le même contexte global sans problème.

Sinon, nous pourrions probablement mettre à jour le message d'erreur et mentionner également ce cas s'il n'est pas trop déroutant.

Oui, j'ai comparé React1 === React2 et c'était false (React1 étant de index.js et React2 étant du fichier utilisant le crochet). Lorsque cela se produit, les crochets échouent avec le message d'erreur générique ci-dessus.

Ce problème vise à sensibiliser à ce cas et peut-être à améliorer le message d'erreur d'une manière ou d'une autre pour aider les personnes qui y sont confrontées. C'est probablement très bord cependant.

Oui, j'ai essayé de lier npm un paquet que je crée. Il génère la même erreur car l'autre package utilise également des hooks mais avec son propre React. J'ai dû publier mon package sur NPM, puis l'importer directement depuis NPM. De cette façon, l'erreur a disparu, mais j'espère que cela est corrigé car publier un paquet sans le tester est mauvais, évidemment

Lerna monorepos en souffre également lorsqu'un hook personnalisé est défini dans un package et utilisé par un autre, car les dépendances liées symboliquement utilisent leur propre copie de react.

J'ai actuellement une solution de contournement (hacky) en utilisant npm-link-shared et un script npm prestart pour remplacer essentiellement la dépendance react d'un paquet par un lien symbolique vers l'autre, donc ils utilisent le même exemple.

"prestart": "npm-link-shared ./node_modules/<other package>/node_modules . react"

J'ai eu le même problème et je l'ai résolu en ajoutant:

 alias: {
        react: path.resolve('./node_modules/react')
      }

à la propriété resolve dans la configuration webpack de mon application principale.

C'était évidemment mon erreur d'utiliser deux copies de React mais je suis d'accord que ce serait génial si le message d'erreur était meilleur. Je pense que c'est peut-être similaire à : https://github.com/facebook/react/issues/2402

@mpeyper Ça marche. Merci

@apieceofbart Cela a fonctionné pour moi. Merci pour la suggestion. 👍

Si je comprends bien, ce problème se pose lorsqu'il y a plusieurs copies de React dans le même bundle.

Est-ce également un problème si deux bundles distincts avec leurs propres copies de React démarrent leurs propres applications React sur des éléments dom séparés, comme décrit ici : https://medium.jonasbandi.net/hosting-multiple-react-applications-on- le-même-document-c887df1a1fcd

Je pense que ce dernier est un modèle "d'intégration" courant utilisé par exemple dans le méta-cadre de spa unique (https://github.com/CanopyTax/single-spa).

J'ai aussi ce problème même avec exactement les mêmes versions de réaction, le développement de crochets à publier par eux-mêmes est cassé lors de l'utilisation npm-link . Obtenir le même message hooks can only be called inside the body of a function component inutile. La solution d'alias de @apieceofbart a résolu ce problème pour moi. Merci beaucoup!

Même problème ici quand je npm link un paquet à mon application principale. Je n'ai pas pu faire fonctionner babel-plugin-module-resolver .
Ça dit:
Could not find module './node_module/react'
C'est ennuyeux car cela m'empêche de tester mon composant en local avant de le publier.

J'ai résolu mon problème en supprimant le caret dans "react": "^16.7.0-alpha.2"
Voici le commentaire complet : https://github.com/facebook/react/issues/14454#issuecomment -449585005

J'utilise Yarn et j'ai résolu ce problème en forçant la résolution dans mon package.json :

  "resolutions": {
    "**/react": "16.7.0-alpha.2",
    "**/react-dom": "16.7.0-alpha.2"
  },

Pareil ici!!

Je voulais juste laisser une note ici pour tous ceux qui auraient pu avoir ce problème de la même manière que moi.

Nous exécutons React et Rails avec la gemme react-rails et rendons les composants directement dans les vues Rails. Je recevais cette erreur à chaque fois qu'une nouvelle version de l'application était poussée, car Turbolinks récupérait le nouveau bundle JS du <head> qui chargeait une instance supplémentaire de React. La solution consistait à demander à Turbolinks de recharger toute la page lorsqu'il détecte que le bundle a changé : https://github.com/turbolinks/turbolinks#reloading -when-assets-change

Cela semble l'avoir résolu pour nous.

Je suis très heureux de pouvoir enfin mettre Hooks en production, et nous devons tous un immense merci à tous ceux qui ont rendu cela possible. Ils sont _ tonne _ de plaisir à travailler et ont rendu mon code plus court et plus déclaratif.

En guise d'avertissement, ce problème est toujours d'actualité dans la version publiée avec le même message d'erreur inutile "Les crochets ne peuvent être appelés qu'à l'intérieur du corps d'un composant de fonction".

Est-ce quelque chose qui peut être corrigé? J'imagine que cela pourrait devenir de plus en plus répandu à mesure que de plus en plus de développeurs commencent à implémenter les nouvelles fonctionnalités, et un message d'erreur plus clair irait loin au lieu d'un "correctif" pur et simple.

Merci encore pour tout le travail acharné et félicitations pour la sortie! C'est vraiment un ensemble incroyable de fonctionnalités.

Edit : J'aurais dû regarder de plus près les PR ouverts, je viens de trouver le numéro 14690 qui résout ce problème. Merci @threepointone !

@taylorham Le lien dans le commit ne pointe encore vers rien. Je vais attendre, mais c'est un problème que j'ai depuis que j'utilise des crochets dans un paquet lié _(à partir de npm link )_ et il est impossible de travailler avec en local sans publier.
Après avoir examiné plusieurs problèmes, j'ai pensé qu'il s'agissait d'un problème avec react-hot-loader qui compilait des composants en classes, mais même après avoir publié une version avec prise en charge de Hook , cela échoue toujours de la même manière.
J'ai essayé beaucoup de hacks différents mais sans succès. Je ne sais pas pourquoi tout le monde n'a pas encore été touché par ce problème 🧐

@dotlouis Ouais, c'est juste un message d'erreur mis à jour jusqu'à présent et le problème lui-même est toujours pénible.

La seule chose qui a fonctionné pour moi est de faire en sorte que l'application que je développe dépende de l'instance de React de la bibliothèque en utilisant "react": "link:../my-library/node_modules/react" .

  • aucune des résolutions proposées n'a fonctionné pour moi, et j'ai tout essayé
  • essayer d'installer sur un contexte de mise en œuvre de projet et beaucoup de HOC
  • partir d'un projet vierge a fait l'affaire
  • je continue à chercher la cause

[ok] pour moi, la correction ne concernait pas package.json ou d'autres causes de double réaction : j'avais un fournisseur de thème global au-dessus de mon application, venant du contexte. Le remplacer par un "useContext Hook" (tout en le réécrivant en tant que comp fonctionnel) semblait être la seule solution
Peut-être y a-t-il un problème lorsque

<GoodOldContext iam={a class component}>
    <BrandNewHook>
             errors : Hooks can only be called inside the body of a function component #35
     </BrandnewHook>
</GooOldContext>
export withGoodOldContext.consumer(here component)

Je développe un composant où il y a un dossier example qui utilise create-react-app .

Faire cela dans package.json a résolu ce problème pour moi :

{
    ...
    "dependencies": {
        "my-component": "link:..",
        "react": "link:../node_modules/react",
        "react-dom": "link:../node_modules/react-dom",
        "react-scripts": "2.1.3"
    },
    ...
}

@taylorham @DylanVann Merci pour votre contribution les gars. Malheureusement, cela ne fonctionne toujours pas pour moi.
Et je n'ai trouvé aucune documentation sur ce protocole link: que vous avez utilisé.
Fondamentalement, il dit que "react-spring" (un autre dep qui utilise également react comme dépendance) ne peut pas trouver react-dom . Pouvez-vous m'indiquer de la documentation sur "react": "link:../some/path" s'il vous plaît ?

J'utilise également le package d'interface utilisateur lié et j'ai pu résoudre ce problème.
Vous devez exporter react renderToString à partir de l'interface utilisateur (package lié).
J'ai créé la fonction de rendu dans le package lié.

Juste pour un meilleur contexte - https://github.com/facebook/react/issues/14257

Merci @theKashey. @gaearon semble penser que c'est le comportement normal. Je comprends que React ne doit pas être chargé deux fois, mais quelle est alors la méthode recommandée pour travailler avec un package local lié ?

J'ai également eu des problèmes avec les espaces de travail Lerna pour obtenir des liens symboliques correctement. C'est l'astuce que j'ai utilisée pour que cela fonctionne. Assurez-vous d'exécuter npm install ensuite.

"dependencies": {
    "react-dom": "file:../common/node_modules/react-dom",
    "react": "file:../common/node_modules/react"
}

Il existe de nombreuses façons de le résoudre, et les résolutions de fil n'aident généralement pas - c'est plus lié à "l'outil de construction"

  • pour le webpack, utilisez aliases - juste un alias "dur" tout se canarde comme react dans un seul fichier
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
    alias: {
     react: path.resolve(path.join(__dirname, './node_modules/react')),
   }
import {setAliases} from 'require-control';
setAliases({
  'react': path.resolve(path.join(__dirname, './node_modules/react'))
});
  • pour plaisanter, utilisez moduleNameMapper
"jest": {
    "moduleNameMapper": {
      "^react$": "<rootDir>/node_modules/$1",
    },

@theKashey merci pour vos idées, cela a du sens si l'on considère la façon dont la résolution des modules est effectuée (en bas, puis en haut de l'arbre), mais du point de vue de l'utilisateur, je ne trouve pas cela très pratique. Lorsque je npm link un paquet, je m'attendrais à ce qu'il fonctionne sans avoir à recâbler explicitement les dépendances. Cela rend le développement d'un package localement assez pénible.

C'est une pierre angulaire, c'est ainsi que node_modules est conçu pour fonctionner, c'est pourquoi vous pouvez avoir deux versions d'un Button dans deux versions majeures différentes, et les modules dépendants trouveront facilement le "bon" version d'un paquet.
C'est ainsi que cela devrait fonctionner tout le temps.

Node.js internes sont assez simples - essayez d'ouvrir un fichier en ajoutant tous les préfixes connus (comme node_modules ) ou extensions (comme js , ts , json ); si aucun n'est trouvé, remontez d'un répertoire. La seule façon de "réparer" - remplacer le système de résolution de module nodejs.

yarn pnp le fera et pourrait résoudre le problème. yarn workspaces , qui pourrait _élever_ les packages partagés au sommet - résoudra également le problème sans aucune "magie" impliquée.

npm workspaces ? N'existe pas pour le moment.

En fait, j'ai fini par changer mon projet pour utiliser des espaces de travail. Il résout ce problème sans avoir à utiliser de résolutions, et le levage/la structure est de toute façon bénéfique.

Celui-ci était un casse-tête. J'ai essayé le paramètre webpack resolve.alias mais cela ne fonctionnait pas, j'ai essayé de nombreux paramètres aussi mais je n'ai jamais vraiment réussi à le faire fonctionner malheureusement, mais voici comment j'ai finalement réussi à le faire fonctionner :

Voici ma structure de dossier :

Projet
|
+-- node_modules
|
+-- construire
| |
| +-- index.js
|
+-- exemple (create-react-app)
| |
| +-- package.json

J'ai dû modifier mon package.json dans le dossier d'exemple, en tirant essentiellement la réaction des node_modules " principaux " du projet en fonction de la suggestion de @jmlivingston , voici comment cela se termine:

  "dependencies": {
    "react": "file:../node_modules/react",
    "react-dom": "file:../node_modules/react-dom",
    "react-scripts": "2.1.5"
  },

Maintenant, après cela, j'ai couru npm install puis j'ai couru npm link , ça a fait l'affaire.

J'espère que cela peut aider quelqu'un d'autre et gagner du temps.

Alors une solution à ce problème ? J'ai essayé autant de recommandations ici que possible et sans succès. J'utilise create-react-app et tapuscrit. Utiliser React/React-dom 16.8.3. Ceci est un nouveau projet que j'ai créé il y a 2 jours, donc assez simple. J'utilise useSpring() et animé.div. Merci

@guru-florida est-ce que vous utilisez react-router par hasard ?

J'utilise la même pile que vous (typescript & create-react-app) et mon problème avec l'attribut render . Le changer en component a fait l'affaire.

Avant de:

<Route path="/signup" render={SignUp} />

Après:

<Route path="/signup" component={SignUp} />

J'espère que ça aide..!

@mikeyyyyyy Non, je n'utilise pas React Router dans celui-ci. Merci pour le conseil, car j'étais dans le dernier projet que j'ai essayé d'utiliser Spring et j'ai eu le même problème.

J'ai eu ce problème avec le lien npm (dans une application de colis), le npm link .../whatever/node_modules/react ne semble pas le résoudre, fonctionne bien avec les composants sans crochet

@tj Je suppose que vous avez un problème avec ssr. La solution de contournement rapide consiste à exporter les fonctions de réaction ou la réaction entière à partir du package lié et à l'importer dans votre package de serveur

@seeden ahh je n'utilise pas SSR, juste un SPA avec Colis. J'ai un pkg ui en interne pour mes propres trucs et une application sur laquelle je travaille, les deux ont la même version react , il semble étrange qu'il y ait un doublon, mais c'est peut-être un problème de colis

@tj oh, je vois. Alors bonne chance avec ce problème très étrange. J'ai passé une semaine avec ça

Alors une solution à ce problème ?

Il n'y a pas de problème ici en soi. Comme expliqué sur cette page , React a besoin que les appels useState() soient sur le même objet react que l'objet react comme "vu" depuis l'intérieur de react-dom . Si ce n'est pas ce qui se passe pour vous, cela signifie que vous regroupez deux copies de React sur la page - ce qui est mauvais en soi et casse également d'autres fonctionnalités avant Hooks. Donc, vous aurez envie de le réparer de toute façon. Cette page contient des méthodes courantes de diagnostic pour le réparer.

Nous laissons cette discussion ouverte pour partager des solutions de contournement particulières lorsque les gens rencontrent ce problème. Mais ce n'est pas un problème en soi qui peut être "réparé" par n'importe qui d'autre que vous.

J'ai eu ce problème avec le lien npm (dans une application de colis), le lien npm .../whatever/node_modules/react ne semble pas le résoudre, fonctionne bien avec les composants sans crochet

Cela vous dérange-t-il de créer un petit étui repro ?

@gaearon fera l'affaire, devrait avoir le temps de creuser un peu plus la semaine prochaine

Heureusement, require-control a résolu notre problème avec le contexte statique de yarn link + SSR + styled-components 4. Merci @theKashey 👍

J'ai tout essayé ici et j'ai échoué. C'était en fait quelque chose de différent non documenté ici. Cela avait à voir avec la sensibilité à la casse des importations de réaction . Dans certains cas, nous avons eu :

import React from 'react'

Et dans d'autres :

import React from 'React'

Sur certains systèmes de fichiers (unix, osx), cela amène Webpack à instancier deux copies de React.

Cela a causé une confusion extrême car je pouvais clairement voir que nous n'avions qu'une seule copie de React; mais c'était plutôt la façon dont nous l'importions.

Le test sur la documentation de réaction est également correct car il n'utilise évidemment que des minuscules.

Cela semble mériter une mention dans les docs ?

Pour moi, la raison de plusieurs instances de React était Webpack DllPlugin. Pour mon fournisseur DLL, je n'ai pas inclus react et react-dom dans ma liste d'entrées, cependant, j'avais d'autres bibliothèques qui nécessitaient react ou react-dom donc ma DLL contenait react et react-dom (une vérification rapide du fichier manifest json peut le révéler). Ainsi, lorsque j'exécutais le code et que j'importais React dans l'application, il le chargeait à partir de node_modules , mais dans le code des fournisseurs, React était requis à partir de leur fichier DLL.

Globalement : soyez prudent avec les fichiers DLL et assurez-vous que vos modules inclus n'incluent pas de dépendances supplémentaires dont vous n'avez pas besoin, sinon vous les importerez deux fois.

J'ai pu résoudre ce problème en mettant à jour react-hot-loader en 4.6.0

cela a fait l'affaire pour les trucs npm link dans Parcel :

"alias": {
        "react": "../ui/node_modules/react",
        "react-dom": "../ui/node_modules/react-dom"
    }

je ne sais pas si c'est ce qu'il essaiera d'utiliser pour une version de production, cela semble un peu hacky mais cela fonctionne au moins pour le développement

@theKashey OMG mec, ça marche ! J'ai essayé de nombreuses solutions différentes que les gens suggèrent en rapport avec ces problèmes: mutiler avec package.json deps, tracer "deux réactions" à travers le projet, vérifier si je viole la * règle des crochets `(que je suis pas), mais je pense que votre option avec:

alias: {
      react: path.resolve(path.join(__dirname, './node_modules/react')),
      'react-dom': path.resolve(path.join(__dirname, './node_modules/react-dom'))
    }

nous permet de déplacer notre projet au niveau suivant, en utilisant des crochets dans notre app-as-a-lib .

Ceci est le résultat webpack.config.js

npm ls react

Retour

[email protected] D:\code\project
`-- (empty)

pour moi

console.log(window.React1 === window.React2) renvoie vrai
à ce stade, je pense que c'est le SSR qui cause le problème

Mettre à jour. Cela a en effet été causé par le comportement SSR de React-apollo (https://github.com/apollographql/react-apollo/issues/2541)
La mise à niveau vers 2.3.1 l'a corrigé

Salut les gars, notre équipe fait face à ce problème et a pris quelques jours pour le régler.

les solutions de travail pour nous

Solution A : spécifiez la position du paquet à rechercher, comme mentionné ci-dessus

  alias: {
      react: path.resolve(path.join(__dirname, './node_modules/react')),
      'react-dom': path.resolve(path.join(__dirname, './node_modules/react-dom'))
    }

Solution B : utilisez webpack resolve.modules pour donner la priorité au bon dossier node_modules pour rechercher des modules

contexte du cas et pourquoi cela se produit

Tout d'abord, ce n'est pas la faute de react, ce n'est même pas celle de lerna, mais react, webpack et npm-link pourraient avoir besoin de prendre certaines responsabilités.

Exigence de cas :

-Non monorepo :

  • avoir des packages liés symboliquement
  • le paquet à lien symbolique a exporté un composant à l'aide de crochets
  • créer des pages côté client de réaction

    • Si vous travaillez sur un monorepo

  • paquets liés symboliquement
  • les packages ont différentes versions de dépendances (même la différence de version de correctif), de sorte que même l'espace de travail résoudra lorsque 2 réagissent installés
  • le paquet d'entrée a importé un paquet à lien symbolique qui utilise des crochets

Exemple

Structure

- mono repo root
  - packages
    - ComponentWithHooks (peerDependency: react@^16.8.1)
    - ProductA (dependency: ComponentWithHooks, dependency: react@^16.8.4)
    - ProductB (dependency: react@^16.8.1)

Une fois le démarrage avec les espaces de travail, il se résoudra à

- mono repo root
  - node_modules
    - react(16.8.1)
  - packages
    - ComponentWithHooks
      - node_modules (empty)
    - ProductA
      - node_modules
        - react(16.8.4)
    - ProductB
      - node_modules (empty)

Et une fois que vous avez servi ProductA avec webpack ou peut-être autre chose, il contiendra 2 instances de réaction.

Le code dans ProductA recherchera ProductA/node_modules/react .

Mais le ComponentWithHooks importé recherchera mono repo root/node_modules/react .

Pourquoi? Vous souvenez-vous des règles de recherche de npm ? S'il ne trouve pas le module dans son propre dossier node_modules, il recherchera le node_modules du parent...

Ainsi, des outils comme Webpack ont ​​parfaitement appliqué cette règle par défaut.
Il n'y a rien de mal à ce que la solution util mono repo soit devenue populaire.
Et le package normal ne le remarquera pas car la plupart d'entre eux ne nécessitent pas d'instance unique comme réagir et redux.

J'ai ce même problème en utilisant une reproduction très basique en utilisant un exemple d'espaces de travail de fil - https://github.com/mwarger/yarn-workspace-hooks-repro

J'ai un component-library écrit en caractères dactylographiés et livré avec un colis. Le example-demo est ce qui mettra en valeur ce component-library et est une application de l'ARC fraîchement créée. Tous les paquets courants sont hissés avec du fil, donc en théorie, il ne devrait y avoir qu'une seule version de réagir disponible. Cependant, l'appel React.useEffect que je fais dans index.tsx provoque l'erreur qui me conduit à ce problème GitHub.

Tout fonctionne jusqu'à ce qu'un crochet soit ajouté. Pour reproduire l'erreur, décommentez les lignes 7 à 9 dans component-library/src/index.tsx

J'espère que je fais quelque chose de stupide que j'ai oublié. Veuillez me conseiller sur les étapes que je peux utiliser pour essayer de remédier à cela. Merci!

Modification de suivi : la sortie du script de débogage suggérée ci-dessous imprime true pour moi. Il semble que je n'ai pas deux Reacts.

// Add this in node_modules/react-dom/index.js
window.React1 = require('react');

// Add this in your component file
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);

Cela m'a pris plusieurs heures, donc ça vaut peut-être la peine de prendre une note ici.

Dans mon cas, j'ai mis une ligne de <script defer src="./dist/bundle.js" /> dans l'en-tête du modèle HTML, qui fonctionne normalement lorsque vous n'utilisez pas les crochets React. Toutes les solutions ne fonctionnent pas et la vérification window.React1 == window.React2 renvoie true dans ce cas.

Étant donné que Webpack injectera la balise de script par la suite, le modèle ne doit pas avoir de balise de script par lui-même. Supprimez la balise de script du modèle pour que React fonctionne à nouveau avec des crochets (jeu de mots).

Dans mon cas, j'ai une application React qui était npm liée à une dépendance sur laquelle je travaillais. Cela fera l'affaire jusqu'à ce que je puisse corriger quelques dépendances qui doivent déplacer react et react-dom vers dev et peer deps.

  1. À partir de l'application : cd node_modules/react && npm link
  2. À partir de l'application : cd node_modules/react-dom && npm link react
  3. À partir du forfait lié : npm link react

Pourquoi ça marche ? La page d'avertissement d'erreur mentionne que "pour que Hooks fonctionne, l'importation de réaction depuis votre code d'application doit être résolue dans le même module que l'importation de réaction depuis l'intérieur du package react-dom".

J'ai toujours ce problème, malgré avoir essayé tout ce qui précède. Configuration standard webpack4/babel, avec les plugins preset-env et preset-react . Mes versions de réaction/réaction-dom sont épinglées à 16.8.4 en utilisant des résolutions de fil (où également la vérification window.React1 === window.React2 ci-dessus renvoie true ).

Il s'agit des utilisations les plus élémentaires :

import React, { useState } from "react";

function MyComp() {
  const [hello] = useState(0);

  return <div>HELLO {hello}</div>;
}
export default MyComp;

Quelqu'un a-t-il d'autres idées?

EDIT: Pour clarifier, l'erreur est affichée comme react.development.js:88 Uncaught Invariant Violation: Hooks can only be called inside the body of a function component. selon l'OP

Dans mon cas, j'ai une application React qui était npm liée à une dépendance sur laquelle je travaillais. Cela fera l'affaire jusqu'à ce que je puisse corriger quelques dépendances qui doivent déplacer react et react-dom vers dev et peer deps.

  1. À partir de l'application : cd node_modules/react && npm link
  2. À partir de l'application : cd node_modules/react-dom && npm link react
  3. À partir du forfait lié : npm link react

Pourquoi ça marche ? La page d'avertissement d'erreur mentionne que "pour que Hooks fonctionne, l'importation de réaction depuis votre code d'application doit être résolue dans le même module que l'importation de réaction depuis l'intérieur du package react-dom".

Merci! Cela fonctionne très bien pour moi. (même lorsque j'utilise un lien npm et une situation mixte de lien symbolique)

J'ai essayé toutes les suggestions ci-dessus et j'avais toujours l'erreur.

Avec un peu d'aide de @inverherive, nous avons constaté que enzyme-adapter-react-16 causait toujours des problèmes.

Alors que nous avons mis à jour react-test-renderer vers la dernière version (16.8.4) car il n'a ajouté que récemment la prise en charge des crochets, nous avons découvert via npm ls react-test-renderer que la dernière version de enzyme-adapter-react-16 (1.11.2 ) avait une dépendance interne de [email protected] , qui ne prend pas en charge les crochets.

├─┬ [email protected]
│ └── [email protected] 
└── [email protected]

Pour résoudre ce problème, ainsi que pour suivre les correctifs de @chulanovskyi , comme nous utilisons du fil, nous avons ajouté des résolutions de react-test-renderer à notre package.json . Cela force toutes les références de react-test-renderer à utiliser "16.8.4".

  "resolutions": {
    "react-test-renderer": "16.8.4"
  },

C'était méga frustrant, j'espère que cela pourra aider quelqu'un d'autre. Merci également à @chulanovskyi et @theKashey pour leurs suggestions.

Cela fera l'affaire jusqu'à ce que je puisse corriger quelques dépendances qui doivent déplacer la réaction et la réaction-dom vers les développeurs et les pairs.

@ajcrews (j'ai peut-être manqué quelque chose mais) j'ai npm link une bibliothèque interne et cette bibliothèque a react dans peerDependencies et devDependencies et j'avais toujours besoin de votre corriger malgré tout pour résoudre l'erreur. Belle trouvaille !

j'étais sur le point de poster mais j'ai trouvé une solution

J'ai une bibliothèque de composants, avec un exemple d'application CRA à l'intérieur pour le développement

Dans le package.json de l'application CRA, j'ai dû modifier react et react-dom pour "emprunter" au package.json du composant racine.

"dependencies": {
  "react": "link:../node_modules/react",
  "react-dom": "link:../node_modules/reac-dom",
}

C'était méga frustrant, j'espère que cela pourra aider quelqu'un d'autre. Merci également à @chulanovskyi et @theKashey pour leurs suggestions.

@Paddy-Hamilton Vérifiez toujours votre fichier de verrouillage après une installation. J'avais rencontré le même problème où yarn duplique react-test-renderer . Avec un peu de chirurgie dans votre fichier de verrouillage, vous pourriez réparer ceux-ci :

yarn add -D react-test-renderer

-react-test-renderer@^16.0.0-0, react-test-renderer@^16.1.1:
+react-test-renderer@^16.0.0-0:
  version "16.8.4"
  resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.4.tgz#abee4c2c3bf967a8892a7b37f77370c5570d5329"
  integrity sha512-jQ9Tf/ilIGSr55Cz23AZ/7H3ABEdo9oy2zF9nDHZyhLHDSLKuoILxw2ifpBfuuwQvj4LCoqdru9iZf7gwFH28A==
  dependencies:
    object-assign "^4.1.1"
    prop-types "^15.6.2"
    react-is "^16.8.4"
    scheduler "^0.13.4"

+react-test-renderer@^16.8.5:
+  version "16.8.5"
+  resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.5.tgz#4cba7a8aad73f7e8a0bc4379a0fe21632886a563"
+  integrity sha512-/pFpHYQH4f35OqOae/DgOCXJDxBqD3K3akVfDhLgR0qYHoHjnICI/XS9QDwIhbrOFHWL7okVW9kKMaHuKvt2ng==
+  dependencies:
+    object-assign "^4.1.1"
+    prop-types "^15.6.2"
+    react-is "^16.8.5"
+    scheduler "^0.13.5"

Un yarn check vous avertirait déjà

$ yarn check
warning "enzyme-adapter-react-16#react-test-renderer@^16.0.0-0" could be deduped from "16.8.5" to "[email protected]"

puis dédoublonnez-le manuellement en appliquant le patch suivant :

-react-test-renderer@^16.0.0-0:
-  version "16.8.4"
-  resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.8.4.tgz#abee4c2c3bf967a8892a7b37f77370c5570d5329"
-  integrity sha512-jQ9Tf/ilIGSr55Cz23AZ/7H3ABEdo9oy2zF9nDHZyhLHDSLKuoILxw2ifpBfuuwQvj4LCoqdru9iZf7gwFH28A==
-  dependencies:
-    object-assign "^4.1.1"
-    prop-types "^15.6.2"
-    react-is "^16.8.4"
-    scheduler "^0.13.4"
-
-react-test-renderer@^16.8.5:
+react-test-renderer@^16.0.0-0, react-test-renderer@^16.8.5:

Vous avez maintenant une version unique de react-test-renderer sans aucune manigance d'alias resolutions ou webpack .

Pour tout problème lié aux packages liés et create-react-app suivez facebook/create-react-app#6207

Il existe de nombreuses façons de le résoudre, et les résolutions de fil n'aident généralement pas - c'est plus lié à "l'outil de construction"

  • pour le webpack, utilisez aliases - juste un alias "dur" tout se canarde comme react dans un seul fichier
  resolve: {
    extensions: ['.ts', '.tsx', '.js', '.jsx'],
    alias: {
     react: path.resolve(path.join(__dirname, './node_modules/react')),
   }
import {setAliases} from 'require-control';
setAliases({
  'react': path.resolve(path.join(__dirname, './node_modules/react'))
});
  • pour plaisanter, utilisez moduleNameMapper
"jest": {
    "moduleNameMapper": {
      "^react$": "<rootDir>/node_modules/$1",
    },

Cela l'a fait pour moi.

@ajcrews
Merci! Fonctionne à merveille pour moi!

J'ai fait un petit cas de test avec une configuration minimale en utilisant React 16.8.6, Electron-Webpack et RHL. Notamment, lorsque cette erreur se produit, l'ensemble du navigateur (dans cette configuration, electron) commence à utiliser tout un tas de temps CPU)

https://github.com/PerfectionCSGO/reeee

Cela fait 3 jours que je me casse la tête sur ce problème. À l'origine, je pensais que RHL était le problème, mais le supprimer entièrement de ce projet ne résoudra pas le problème.

npm ls react renvoie un seul résultat. Je me suis assuré que le correctif ci-dessus est appliqué avec les dernières versions + alias webpack.

Le code fonctionnera dans un bac à sable.

Dans un simple webpack/site web, le code fonctionnera sans problème. Cependant, avec electron-webpack, ce problème persiste.

  "dependencies": {
    "i18next": "^15.0.9",
    "i18next-browser-languagedetector": "^3.0.1",
    "react": "^16.8.6",
    "react-dom": "npm:@hot-loader/react-dom",
    "react-hot-loader": "^4.8.2",
    "react-i18next": "^10.6.1",
    "source-map-support": "^0.5.11",
    "tslint": "^5.15.0"
  },
  "devDependencies": {
    "@babel/core": "^7.4.3",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.3.3",
    "@types/react": "^16.8.12",
    "@types/react-dom": "^16.8.3",
    "electron": "^4.1.3",
    "electron-builder": "20.39.0",
    "electron-webpack": "^2.6.2",
    "electron-webpack-ts": "^3.1.1",
    "typescript": "^3.4.1",
    "webpack": "^4.29.6"
  }

J'espère que quelqu'un pourra me donner une piste...

Lorsque je remplace react-l18next par mobx-react-lite et que j'utilise observer, cela provoquera le même effet.

En ce qui concerne mon problème, je l'ai résolu en coudant électron-webpack et en optant pour une solution électronique plus "pure". Je suppose que c'est une chaîne d'outils utilisée dans webpack ou babel qui est incompatible.

J'ai rencontré ce problème uniquement en production. Aucune des solutions proposées ici n'a aidé.
Mon cas d'utilisation était une application tierce qui se charge en tant que widget sur un autre site Web.
Lorsque le site a été chargé pour la première fois avec le widget, tout fonctionnait bien, mais lorsque l'utilisateur naviguait vers une autre page et revenait à la page avec le widget, j'obtenais l'erreur de crochets.

Notez que l'erreur ne se produit que lorsque la navigation ne provoque pas de rechargement de page.

J'ai passé des heures à essayer de comprendre d'où venait le problème. Enfin, le problème était avec l'extrait de code qui charge le bundle d'applications. Lors du changement de page, le bundle pouvait se charger plusieurs fois, ce qui provoquait, je suppose, plusieurs instances de React dans le même espace de noms.

Je l'ai corrigé en vérifiant si le script a déjà été chargé.
J'ai d'abord exporté ma bibliothèque vers l'espace de noms global en utilisant la configuration "bibliothèque" de Webpack :

output: {
    library: 'myLib',
    ...
}

Et puis dans le script de chargement j'ai vérifié si la bibliothèque existe ou non :

if(!window.myLib){
    var bz = document.createElement('script');
    bz.type = 'text/javascript'; 
    bz.async = true;
    bz.src = 'https://path/to/bundle.js';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(bz, s);
}

Il peut s'agir d'un cas d'utilisation très spécifique, mais j'espère que cela pourra aider quelqu'un d'autre.

Nous avons donc une application React principale tirant parti de webpack.
Nous essayons de créer une petite bibliothèque React qui utilise des hooks, nous avons essayé d'échanger des bundlers (parcel, pure babel, webpack).
Lors de l'essai de notre implémentation de webpack, nous avons marqué react et react-dom comme externes, nous ne les inclurons donc pas dans notre bundle.
Nous obtenons toujours la même exception de crochets lors de l'utilisation du lien npm.

La création d'un lien symbolique vers la réaction de l'application principale fonctionne, mais ce n'est pas un excellent workflow de développement.

J'ai du mal à comprendre la cause sous-jacente du problème. Qu'est-ce qui produit une instance React en double ?

Bonjour @adriene-orange , vous trouverez peut-être mon post https://github.com/facebook/react/issues/13991#issuecomment -472740798 pour plus d'explications.

La multi-instance causée par le lien npm est due au fait que le nœud par défaut recherchera dans les node_modules du dossier parent pour le module s'il ne peut pas le trouver dans votre package.

La solution la plus simple et la meilleure que nous trouvions pour cela est dans la configuration du pack d'entrée (ou d'autres outils) de votre package d'entrée, il y a quelque chose comme resolve.modules pour définir manuellement les chemins et commander les chemins que le webpack recherchera pour les modules. Exp., resolve: { modules: [path.resolve(PACKAGE_ROOT, 'node_modules'), 'node_modules'] } , forcera Webpack à trouver d'abord les modules dans le node_module de la racine de votre package d'entrée. Si vous ne trouvez pas le module à la racine, recherchez-le dans le dossier node_modules relatif...

Nous avons donc une application React principale tirant parti de webpack.
Nous essayons de créer une petite bibliothèque React qui utilise des hooks, nous avons essayé d'échanger des bundlers (parcel, pure babel, webpack).
Lors de l'essai de notre implémentation de webpack, nous avons marqué react et react-dom comme externes, nous ne les inclurons donc pas dans notre bundle.
Nous obtenons toujours la même exception de crochets lors de l'utilisation du lien npm.

La création d'un lien symbolique vers la réaction de l'application principale fonctionne, mais ce n'est pas un excellent workflow de développement.

J'ai du mal à comprendre la cause sous-jacente du problème. Qu'est-ce qui produit une instance React en double ?

Salut, je reçois cette erreur

Violation invariante : appel de crochet non valide. Les crochets ne peuvent être appelés qu'à l'intérieur du corps d'un composant de fonction. Cela peut se produire pour l'une des raisons suivantes :
1. Vous pouvez avoir des versions incompatibles de React et du moteur de rendu (comme React DOM)
2. Vous enfreignez peut-être les règles des crochets
3. Vous pouvez avoir plusieurs copies de React dans la même application
Voir https://fb.me/react-invalid-hook-call pour des conseils sur la façon de déboguer et de résoudre ce problème.

   5 | 
   6 | const useApiHelper = (url, reducer) => {
>  7 |     const [state, dispatch] = useReducer(reducer, {});
     |                                                  ^
   8 | 
   9 |     useEffect(() => {
  10 |         fetch(url).then(res => res.json())

Exemple de code https://stackblitz.com/edit/react-mbze9q

Lorsque j'essaie d'accéder à cette fonction dans des cas de test, j'obtiens l'erreur ci-dessus

@abhishekguru Vous appelez le Hook en dehors d'un composant ici dans votre test :

test('API test', async () => {
  const newState = useAPIHelper( // <- Called outside of a component
    'https://jsonplaceholder.typicode.com/posts',
    reducer
  )
  console.log(newState, 'new');
  // expect(newState[samUrl].loading).toEqual(true);
});

Comme l'indique l'erreur, les crochets ne peuvent être appelés qu'à partir d'un autre crochet ou à partir d'un composant. Dans votre cas, vous pouvez créer un composant pour votre test et afficher ce composant qui utilise le crochet si vous le souhaitez.

Prise sans vergogne

@abhishekguru si vous avez un hook générique utilisé entre plusieurs composants et que vous souhaitez le tester indépendamment d'un composant particulier, vous pouvez envisager d'utiliser react-hooks-testing-library .

import { renderHook } from 'react-hooks-testing-library'

test('API test', async () => {
  const { result } = renderHook(() => useAPIHelper( // <- now called within a component
    'https://jsonplaceholder.typicode.com/posts',
    reducer
  ))

  console.log(result.current, 'new');
  // expect(result.current[samUrl].loading).toEqual(true);
});

Je voulais intervenir ici parce que nous avions des problèmes avec SSR uniquement. Nous effaçons les require.cache du nœud lors des modifications de fichiers. Cela donne effectivement un rechargement à chaud sur le serveur. Effacer require.cache du nœud causera des problèmes avec les bibliothèques qui ont besoin d'avoir une seule copie. Voici notre solution :

Object.keys(require.cache)
  .filter(key => !isSingleton(key)) // This is needed here because react cannot be deleted without causing errors
  .forEach(key => {
    delete require.cache[key]
  })

Notre fonction isSingleton contient la liste des bibliothèques qui doivent avoir une seule copie. Une bonne règle de base est toute bibliothèque qui doit être définie dans peerDependencies

https://yarnpkg.com/lang/en/docs/dependency-types/#toc-peerdependencies

J'ai également eu le même problème et pour moi

window.React1 = require('react');
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2); // true

a également renvoyé true , a essayé toutes les suggestions données mais rien n'a fonctionné. Finalement il s'est avéré que :

Webpack ajoute automatiquement la balise de script avec le bundle.js dans le index.html . Mon problème était que j'ajoutais explicitement le bundle.js dans index.html , ce qui fonctionnait bien avant les crochets.

Pour moi, le problème était après la mise à niveau de Babel 7, il n'y avait pas de versions distinctes avec npm ls react. Suppression
"react-hot-loader/babel" de .babelrc a temporairement corrigé le problème.

J'ai essayé toutes les solutions ci-dessus, mais j'ai toujours l'erreur.
Finalement, j'ai découvert que cela était dû au package why-did-you-update , et qu'il y avait un problème connexe. Juste un indice pour quiconque utilise un package similaire qui modifie React.

J'ai pu résoudre ce problème dans un scénario react-native + Yarn Workspaces .


À la racine package.json

{
  "private": true,
  "workspaces": {
    "packages": [
      "packages/*"
    ],
    "nohoist": [
      "**/react-native",
      "**/react-native/!(react)/**"
    ]
  }
}

Cela empêche le code react-native d'être hissé (comme cela est nécessaire pour réagir natif), tout en continuant à hisser react , ce qui permet à tous les modules partagés d'utiliser la même réaction.


Dans le metro.config.js

module.exports = {
  watchFolders: [
    path.resolve(__dirname, '../', 'shared-module'), 
    // ...more modules
    path.resolve(__dirname, '../', '../') // to make sure the root `react` is also part of the haste module map
  ]
}

La configuration du métro permet au bundler de savoir où tout se trouve.

J'ai trouvé un moyen de résoudre le problème pour les personnes qui développent localement un package npm par exemple, et elles essaient de le tester localement en chargeant leur package à l'aide du lien npm dans une sorte d'exemple d'application.

Je suis passé de l'exemple d'application (manière originale de tester le composant) à Storybook . Lors de l'utilisation du livre d'histoires dans le projet, il ne chargera pas React deux fois car il utilisera le même que celui utilisé par le composant. Lors de l'utilisation du lien npm, j'ai eu des problèmes avec les crochets et le chargement de React deux fois, et je n'ai pas pu faire fonctionner l'une des solutions ci-dessus. Storybook a donc résolu mon problème, et maintenant j'ai un moyen de tester mon composant à travers plusieurs scénarios et en même temps de créer une documentation interactive pour celui-ci.

Partageant mon expérience avec ceci, je l'ai résolu pour notre projet en utilisant des externes webpack pour la bibliothèque de composants afin d'exclure react et react-dom de la construction.

Nous commençons tout juste avec React. Dans mon cas, nous commençons avec Lerna monorepo avec le package de bibliothèque de composants Neutrino et le package client Webapp Neutrino. L'application Web utilise le produit de génération de la bibliothèque de composants liés. Après quelques expériences et avoir obtenu true pour la même instance React, j'ai cherché un moyen d'exclure react et react-dom de la construction de la bibliothèque de composants.

Cela semble être une solution de modèle de conception courante pour les bibliothèques de composants Webpack, donc dans la bibliothèque de composants, j'ai ajouté à la configuration Webpack :

"externals": {
  "react": "react",
  "react-dom": "react-dom"
}

Je n'ai pas eu besoin de mettre une balise de script globale dans le package webapp pour react et react-dom . Je suppose que Webpack les fournit à la bibliothèque de composants dans son implémentation require la même manière qu'il fournit à l'application Web.

une autre cause de cette erreur est la mauvaise configuration de Route React Router,

Cela échoue :

<Route render={MyHookedComponent}/>

, mais cela réussit :

<Route component={MyHookedComponent}/>

Par exemple. vous devez utiliser component non render . C'est une erreur facile à faire car render fonctionne généralement bien avec les composants basés sur les classes.

Je travaillais sur biolerplate et je voulais le publier sur npm, et développer à l'aide du lien npm Cela fonctionnait correctement mais après un certain temps, j'ai commencé à donner des erreurs Invalid Hook call warning .
J'ai essayé d'utiliser le lien npm ../myapp/node_modules/react mais cela ne résout pas mon problème,
Et par rapport React1 === React2 c'est vrai ainsi qu'à npm ls react également fait, il ne montre qu'un seul paquet.

Et je n'utilise pas non plus Webpack, j'ajoute simplement une couche en dehors de create-react-app afin que je ne puisse pas forcer mon application à utiliser le module de réaction installé localement.
Coincé avec ça depuis 3 jours._

Identique à @hnagarkoti .

J'ai rencontré cet avertissement lors du rendu côté serveur (SSR) parce que j'utilisais une ancienne version de react-apollo donc je voulais juste laisser ce lien ici pour aider la prochaine âme qui rencontre ce problème :

https://github.com/apollographql/react-apollo/issues/2541

En bref, getDataFromTree ne prend pas en charge les hooks de réaction jusqu'à la version [email protected] .

J'ai eu le même problème et je l'ai résolu en ajoutant:

 alias: {
        react: path.resolve('./node_modules/react')
      }

à la propriété resolve dans la configuration webpack de mon application principale.

C'était évidemment mon erreur d'utiliser deux copies de React mais je suis d'accord que ce serait génial si le message d'erreur était meilleur. Je pense que c'est peut-être similaire à : #2402

Des suggestions pour faire cela avec create-react-app ?

^ Ok, la solution que j'ai choisie pour résoudre ce problème pour create-react-app consiste à utiliser react-app-rewired et customize-cra.

Voici mon config-overrides.js :

const {
    override,
    addWebpackAlias,
  } = require("customize-cra");

const path = require('path'); 

module.exports = override( 
    addWebpackAlias({
        react: path.resolve('./node_modules/react')
    })
)

Exemple de projet : https://github.com/dwjohnston/material-ui-hooks-issue/tree/master

Dans notre équipe, nous avons un composant de navigation universel qui fonctionne sur des dizaines d'applications, toutes ces applications proviennent de réagir 15.0.0 à réagir 16.8.0, afin de permettre la navigation implémentée au-dessus des crochets, nous devons le regrouper avec une dernière réaction

Dans ce cas, avoir plusieurs instances de réaction est une exigence fondamentale pour nous, j'aimerais savoir si l'équipe officielle de réaction est prête à résoudre ce problème à l'avenir ?

@dwjohnston ma solution de contournement pour create-react-app consistait à créer une configuration Webpack pour le développement. create-react-app utilise en interne webpack, webpack-dev-server et le babel-loader, donc créer une configuration webpack juste pour le développement n'était pas trop mal car les dépendances sont déjà implicitement là mais encore une bonne quantité de frais généraux pour obtenir le fonctionnement correct.

J'ai un problème sur create-react-app : https://github.com/facebook/create-react-app/issues/6953 pour ajouter le support Webpack alias ou similaire.

👋 Si quelqu'un utilise également create-react-app et rencontre ce problème, pourriez-vous s'il vous plaît donner un coup de pouce à ce problème ?

@ricokahler - Merci de l'avoir signalé. Je suis heureux de voir que je ne suis pas la seule personne à avoir ce problème - je l'ai également rencontré avec le contexte.

Connaissez-vous des ressources qui discutent davantage de cette question ?

Si vous êtes dans mon bateau, vous avez ajouté un package de composant de réaction à partir d'un répertoire local, et maintenant il le construit et l'installe automatiquement, avec sa propre copie de node_modules (car il utilise le lien npm pour ce faire), donnant votre app 2 copies ou Réagissez maintenant.

J'ai contourné le problème en supprimant le node_modules//node_modules avant d'exécuter l'application. Pour le faire automatiquement :

"prestart": "rimraf ./node_modules/<my_package>/node_modules"

J'ai également été confronté à cela lors de la SSR.
Si vous utilisez Lerna pour tester localement votre bibliothèque React, vous pouvez ajouter "react/react-dom/react-router" en tant que peerDependencies sur votre bibliothèque, mais vous ne devez pas les ajouter en tant que devDependencies. (cela en fait un doublon)
Vous pouvez utiliser node --preserve-symlinks pour qu'il puisse rechercher le référentiel parent qui installe les peerDependencies.
Pour jest, vous devez ajouter le chemin du référentiel parent à l'option "jest.moduleDirectories" afin que Jest puisse les résoudre

@apieceofbart ça marche pour moi, merci !

J'ai rencontré cette erreur lors du chargement de composants React externes, par exemple avec des modules JS. Ils sont complètement en dehors du projet, chargés avec une importation dynamique() (enfin jsonp pour plus de support). Pour contourner le problème, nous passons/injectons React comme propriété à chaque module. Cela fonctionne, mais chaque module dépend de l'application React qui le contient. Nous essayons de supprimer les dépendances.

Comme d'autres l'ont mentionné, cette propriété élimine React comme utilisable pour tout type de micro frontal. Le problème est qu'il y a cet effet secondaire de créer un état global dans le runtime JS lors de l'importation de React à utiliser comme bibliothèque.

Je comprends que pour des cas d'utilisation simples, avoir cet effet secondaire signifie que React est "plus facile à utiliser". Mais lorsqu'une page Web est composée de plusieurs scripts provenant de plusieurs étapes de bundle, l'un d'eux doit être capable de configurer React (faire explicitement cet effet secondaire) et les autres peuvent simplement appeler des fonctions de bibliothèque.

J'ai toujours un problème avec react-bootstrap : # https://github.com/react-bootstrap/react-bootstrap/issues/3965

Pour tous ceux qui essaient de créer une bibliothèque pour React, essayez https://github.com/whitecolor/yalc , cela fonctionne beaucoup mieux que les liens symboliques.

@mpeyper fonctionne bien. THX

@apieceofbart Cela a fonctionné pour moi. Merci pour la suggestion. 👍

Pour moi, ce problème a été causé lorsque j'ai navigué vers mon répertoire de projet dans PowerShell et que je n'ai pas mis en majuscule un nom de répertoire dans le chemin. J'ai créé le projet dans users/…/… au lieu de Users/…/...
Le problème a été résolu lorsque j'ai corrigé les erreurs de capitalisation et recréé le projet.

Pour moi, faire :

    "react": "file:../my-library/node_modules/react",
    "react-dom": "file:../my-library/node_modules/react-dom",

La plupart ont été corrigés, mais ce n'était pas suffisant, j'ai continué à recevoir l'erreur hooks can only be called inside the body of a function component .

Il s'avère que c'est parce que certains des composants de ma bibliothèque ont été exportés comme suit :

export default Radium(withTranslation()(MyComponent))

:X:

withTranslation est le HOC de react-i18next et Radium est le HOC de Radium.

Et les exporter comme ceci:

export default withTranslation()(Radium(MyComponent))

:heavy_check_mark:
Tout réparé.

Notez que react-i18next était dans la version 10 qui utilise React Hooks

@mikeaustin Nous avons le même problème. Avez-vous un exemple de "passage/injection de React en tant que propriété à chaque module" ?

Toujours ce problème, j'ai essayé toutes les étapes :

  • espaces de travail du fil (via lerna)
  • vérifié s'il y a un dep de réaction, oui

Certaines choses qui peuvent avoir un impact :

  • utiliser webpack avec libraryTarget
  • en utilisant le texte dactylographié
$ npm ls react-dom
/xxx
└── [email protected]

$ npm ls react
/xxx
└── [email protected]

package racine.json

{
  ...
  "workspaces": [
    "packages/*",
  ],
  "devDependencies": {
    ...
  },
  "dependencies": {
    "react": "16.8.6",
    "react-dom": "16.8.6"
  },
  "resolutions": {
    "react": "16.8.6",
    "react-dom": "16.8.6",
    "**/react": "16.8.6",
    "**/react-dom": "16.8.6"
  }
}

@JeremyGrieshop J'ai eu le même problème et cela a fonctionné pour moi, merci.

Ajoutez "prestart" dans votre package.json comme ci-dessous :

"scripts": {
    "prestart": "rimraf ./node_modules/<my package>/node_modules",
    "start": "react-scripts start",
    "build": "react-scripts build",
  },

J'ai eu ce problème et ce n'était pas dû à plusieurs versions de react/react-dom
Dans l'outillage personnalisé que j'utilise, le cache requis a été effacé (dans un but en dehors de cette discussion), par exemple :

Object.keys(require.cache).forEach((key) => {
      delete require.cache[key];
    });

Donc, pour votre information, si vous faites quelque chose comme ça, cela affectera React Hooks, alors évitez-le si vous le pouvez.

J'ai eu le même problème et je l'ai résolu en ajoutant:

 alias: {
        react: path.resolve('./node_modules/react')
      }

à la propriété resolve dans la configuration webpack de mon application principale.

C'était évidemment mon erreur d'utiliser deux copies de React mais je suis d'accord que ce serait génial si le message d'erreur était meilleur. Je pense que c'est peut-être similaire à : #2402

Pour tous ceux qui utilisent Parcel, si dist est l'endroit où se trouvent vos fichiers compilés, vous devez ajouter :

  "alias": {
    "react-mediator": "./dist"
  },

À votre package.json , puis vous pouvez toujours link (npm ou fil) la bibliothèque pour le développement/test local.

@mikeaustin Nous avons le même problème. Avez-vous un exemple de "passage/injection de React en tant que propriété à chaque module" ?

Vous pouvez utiliser React Context pour transmettre "React" lui-même et créer un HoC pour injecter la propriété dans chaque composant. Vous pouvez passer n'importe quoi dans api comme api.React, mais cela devient un peu délicat d'envelopper les HoC autour de ces composants (car maintenant ils ne sont disponibles qu'à l'intérieur d'un composant, non disponibles pour l'exportation.

const withReact = Component = props => (
  <ReactContext.Provider value={api => <Component api={api} {...props} /> } />
)

Je passe quelques heures dessus, si changer le code source pour modifier le message d'erreur et y ajouter plus d'informations n'est pas facile et que vous avez besoin de plus de temps, ajoutez au moins cette note dans la doc ,

_ps : react contient une excellente documentation, mais je pense que cette page doit être révisée._

@OliverRadini

J'ai pu résoudre ce problème en mettant à jour react-hot-loader en ^4.6.0

Maaan, ça a réglé le problème.
@gaearon @theKashey Que diriez-vous d'ajouter ceci à https://reactjs.org/warnings/invalid-hook-call-warning.html afin que les gens ne perdent pas leur temps à cause d'une ancienne version de react-hot-loader ?

Je pensais que c'était déjà assez bien documenté sur une douzaine de problèmes.

Bonjour, j'utilise React à la fois dans une application et dans une bibliothèque . J'utilise la bibliothèque à l'intérieur de l'application. J'ai réussi à résoudre le problème des deux instances de réaction en utilisant :

Dans la configuration du webpack de l' application :

    alias: { react: path.resolve( '__dirname', '..',  'node_modules', 'react' ) // Adapt this to match your file tree

Dans la configuration du webpack de la bibliothèque

  externals: {
    react: 'react', // Case matters here
    'react-dom': 'react-dom' // Case matters here
  }

Je rencontre donc un problème avec l'appel de hooks à partir d'un fichier non transpilé (*.js):

index.js :

import ReactDOM from 'react-dom';
import './index.css';
import App from './app';

ReactDOM.render(App(), document.getElementById('root'));

app.jsx

import React from 'react';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom';
const BaseContext = React.createContext();

const initialState = {
  woo: true
};

const reducer = (state, action) => {
  switch (action.type) {
    default:
      return state;
  }
};

const Home = () => <h1>You're at home.</h1>;

const App = () => {
  // eslint-disable-next-line
  const [state, dispatch] = React.useReducer(reducer, initialState);
  return (
    <Router>
      <BaseContext.Provider value={initialState}>
        <BaseContext.Consumer>
          <div className="welcome">
            <nav>
              <ul>
                <li>
                  <Link to="/">Home</Link>
                </li>
              </ul>
            </nav>
            <header className="header">
              <h1>Welcome!</h1>
            </header>
            <Route path="/" exact component={Home} />
          </div>
        </BaseContext.Consumer>
      </BaseContext.Provider>
    </Router>
  );
};
export default App;

Un conseil, en supposant que ce n'est pas "Déplacez-le dans le fichier JSX et transpilez" ?

Rien ne semble fonctionner pour moi, j'utilise un mélange de stimulus et de réaction, j'ai une application hybride, j'ai commencé à utiliser des crochets et cela a échoué dès que j'ai commencé à ajouter des turbolinks :(

Edit : pour l'instant, j'ai résolu mon problème en ajoutant data-turbolinks-track="reload" data-turbolinks-eval="false" aux balises de script que j'utilise, ce qui devrait le faire pour l'instant

j'ai la même question, après 4 heures, j'étais une source qui était jenkins util manquant transformer les fichiers .babelrc en serveur。。。

Pourquoi cela créerait-il l'erreur ?

$ npm ls react
[email protected] /mnt/g/development/javascript/pow-vehmain
└── [email protected]`
Invalid hook call...
ServiceVisitMaintenance
src/components/ServiceVisit/ServiceVisitMaintenance.js:6
  3 | import { ServiceVisitForm } from './ServiceVisitForm';
  4 | 
  5 | const data = [{ id: 1, description: 'Ford' }, { id: 10, description: 'Edsel' }];
> 6 | const ServiceVisitMaintenance = () => {
  7 |   const [vehicleList, setVehicleList] = useState([]);
  8 |   return (
  9 |     <div>

ServiceVisitMaintenance.js :

import React, { useState } from 'react';
import { ServiceVisitForm } from './ServiceVisitForm';
const data = [{ id: 1, description: 'Ford' }, { id: 10, description: 'Edsel' }];
const ServiceVisitMaintenance = () => {
  const [vehicleList, setVehicleList] = useState([]);
  return (
    <div>
      <ServiceVisitForm vehicleList={data} />
    </div>
  );
};

export { ServiceVisitMaintenance };

Veuillez vérifier quelle est votre version de react-dom.

$ npm ls réagir-dom
[email protected] /mnt/g/development/javascript/pow-vehmain
└── [email protected]

J'ai été confronté à cela lorsque j'ai exporté un connect(mapStateToProps)(MyComponent) de la bibliothèque et que j'ai utilisé cette bibliothèque dans mon application CRA.

Non, c'était ma mauvaise erreur. La routine qui l'appelait utilisait react-router-dom et utilisait le render prop plutôt que le composant.

Est-ce que l'un d'entre vous a eu le même problème mais avec Gatsby ?

J'obtiens le résultat suivant après que j'ai 'npm ls react':
image

et 'npm ls react-dom'
image

Au début, je pensais avoir accidentellement installé réagir globalement, après la désinstallation globale, rien n'a changé. Ensuite, j'ai essayé de créer un projet entièrement nouveau dans un répertoire différent, "gatsby new random-name" et j'ai ajouté une petite fonctionnalité (ajoutez des commentaires, en suivant https://www.youtube.com/watch?v=asrdFuAxPaU&feature=youtu .be) au gatsby-starter-default pour tester si l'erreur se reproduirait. Eh bien, à mon grand dam, c'est le cas !

Tout conseil serait bien reçu par une plèbe frustrée.

Je suis toujours confronté à ce problème dans le livre de contes. Cette sortie de npm ls est-elle correcte ou non ?
imageimage

Dans mon cas, le problème a été causé par le module why-did-you-update .

Utilisez l'espace de travail et lerna monorepo et soulevez le paquet. cela résoudra le problème.

nous avons le même problème avec SSR. cela semble fonctionner en définissant externals: [“react”] dans notre configuration webpack puis en chargeant manuellement react/umd/react.development.js . c'est une douleur, cependant et aimerait trouver un moyen plus simple.

Ok alors j'espère que cela aide quelqu'un. Nous avons chargé le webpack runtime.js plusieurs fois accidentellement, ce qui a provoqué l'existence de plusieurs copies de React. Assurez-vous de ne charger le runtimeChunk (runtime.js) qu'une seule fois.

Si vous avez le problème avec vos tests Jest comme moi, c'est ce qui semble le résoudre pour moi.
Ajoutez ceci dans votre jest.config.js

moduleNameMapper: {
    '^react$': '<rootDir>/node_modules/react/'
  }

Ce serait bien si cette erreur pointait au moins vers le fichier où cela se passe. J'ai accidentellement appelé un crochet dans une fonction normale et il était difficile de déboguer.

J'ai trouvé une autre cause du problème et une solution.

Mon environnement est electron et webpack mais cela pourrait aussi aider les non-électron. J'ai passé des jours pénibles à essayer de résoudre pourquoi je reçois ce message d'erreur après la mise à niveau vers React 16.9 (et React DOM 16.9).

Dans mon cas, il semblait que j'avais deux Reacts dans l'application, mais je n'ai pas pu trouver deux bibliothèques physiques dans node_modules, même pas en utilisant npm ls react . J'ai même utilisé webpack-bundle-analyzer pour voir ce qu'il y a à l'intérieur du paquet.

Finalement, j'ai découvert que je n'avais pas physiquement deux réactions dans le projet, mais React et React DOM ont été référencés/chargés deux fois dans le fichier HTML . Cela peut être facilement vérifié en ajoutant par exemple console.log("React load") à l'index.js de la bibliothèque React.

La vraie source était connectée à electron-webpack . react et react-dom n'ont pas été marqués comme externes et ont donc été chargés dans le bundle ainsi que plus tard à partir de node_modules en raison de la nécessité d'être utilisés dans un autre module.

La solution était aussi simple que d'ajouter ces lignes à webpack.renderer.config.js :

module.exports = {
    externals: [
        "react",
        "react-dom"
    ],
};

D'accord, donc si quelqu'un ici utilise parcel.js, pour une raison étrange, j'ai pu m'en tirer avec l'importation suivante : import React from 'React'; et une fois que j'ai commencé à utiliser des crochets de réaction, j'ai eu l'erreur de violation invariante sans réaliser que c'était parce que j'importais incorrectement en utilisant from 'React' au lieu de from 'react' . Oups.

Est-ce que l'un d'entre vous a eu le même problème mais avec Gatsby ?

J'obtiens le résultat suivant après que j'ai 'npm ls react':
image

et 'npm ls react-dom'
image

Au début, je pensais avoir accidentellement installé réagir globalement, après la désinstallation globale, rien n'a changé. Ensuite, j'ai essayé de créer un projet entièrement nouveau dans un répertoire différent, "gatsby new random-name" et j'ai ajouté une petite fonctionnalité (ajoutez des commentaires, en suivant https://www.youtube.com/watch?v=asrdFuAxPaU&feature=youtu .be) au gatsby-starter-default pour tester si l'erreur se reproduirait. Eh bien, à mon grand dam, c'est le cas !

Tout conseil serait bien reçu par une plèbe frustrée.

Oui j'ai rencontré le même problème que vous. J'ai suivi les conseils ici... ,

// Add this in node_modules/react-dom/index.js
window.React1 = require('react');

// Add this in your component file
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);

J'ai ajouté React2 pour indexer le fichier sous les pages. Il renvoie faux.

Deduped signifie que npm aurait dû dédupliquer la dépendance voir ici...

Le même paquet n'a pas besoin d'être installé deux fois ! C'est juste référencé.

En outre, il déplace les packages "vers le haut de l'arborescence" (aplatit l'arborescence). Cela est tout à fait logique car sinon un paquet devrait regarder dans les node_modules d'un autre paquet (ce qui serait un peu désordonné) et aide à simplifier les dépendances.

Vous pouvez valider cela, car chaque package de votre graphique de dépendance qui indique dédupliqué peut être trouvé au moins une fois de plus dans le graphique, généralement à un "niveau supérieur".

Bien qu'évidemment le dédoublonnage n'ait pas fonctionné.

Qu'as-tu essayé ?

J'obtiens cette erreur lorsque j'essaie de construire avec NextJS. Certains composants utilisent material-ui et le problème disparaît si je les supprime. Je n'utilise pas de composants de style. J'ai essayé de supprimer node_modules etc. sans succès. J'ai essayé d'ajouter des alias et des résolutions pour react dans mon fichier next.config.js et package.json sans succès. J'utilise react 16.8.6, react-dom 16.8.6 et next 9.0.4. npm ls indique qu'il n'y en a qu'un de chaque. Je n'utilise aucun lien npm.

Référentiel : https://github.com/dancancro/questions/tree/invalid-hook-call

Codesandbox est ici : https://codesandbox.io/s/github/dancancro/questions/tree/invalid-hook-call/?fontsize=14

Stackoverflow : https://stackoverflow.com/questions/57647040/nextjs-invalid-hook-call-hooks-can-only-be-called-inside-of-the-body-of-a-fun

L'erreur est ici : https://gist.github.com/dancancro/2dfafb053aaaedfade406fd4f67eb68a
... rendu -> renderToString -> ReactDOMServerRenderer.read -> ReactDOMServerRenderer.render -> Object.WithStyles [as render] ...

Le hook incriminé est un appel useStyles() à la ligne 17428 du fichier suivant dans une fonction withStyles . Recherchez "var classes = useStyles(props)". Le problème est avec le code généré par nextjs. Le code que j'ai écrit n'utilise pas withStyles ni aucun hook ni aucune fonction commençant par "use*"

https://raw.githubusercontent.com/dancancro/questions/invalid-hook-call/.next/static/development/pages/index.js

MISE À JOUR : la suppression de ceci de mon next.config.js a résolu le problème :

    webpack: config => {
        config.externals = [
            '/'
        ]
        return config
    },

J'ai découvert une solution de contournement en supprimant react et react-dom du dossier node_modules $ de mon package lié.

Je suis dans le même bateau que beaucoup d'entre vous. J'ai un package de bibliothèque sur lequel je travaille localement et je ne veux pas me soucier de le publier chaque fois que j'ai besoin de voir des modifications dans mon package d'application. Je l'ai lié et j'ai commencé à avoir cette erreur.

Voici la solution :

  • Package A : votre package de code de bibliothèque a été npm link 'd
  • Package B : votre package de code d'application. A un lien symbolique dans votre dossier node_modules pour le package A
  1. Construisez le package A. Le mien génère ses actifs dans dist/ , y compris c'est node_modules
  2. Dans le dossier node_modules distribué du package A, supprimez react et react-dom
  3. ???
  4. Profit!

Notez que j'avais installé la même version de React dans les deux packages. Vous devrez redémarrer tous les processus en cours d'exécution.

Supprimer why-did-you-update incompatibles fonctionne pour moi. (https://github.com/maicki/why-did-you-update/issues/52)

incompatible pourquoi avez-vous mis à jour

@bertho-zero use peut utiliser les nouveaux devtools ou mon crochet useWhyDidYouUpdate

@brunolemos C'est super mais plus contraignant car il faut en mettre sur chaque composant.

La solution de @ dmart914 a résolu le problème pour moi. J'ai moi aussi des packages liés afin que je puisse tester ma bibliothèque sans publier de modification... quelqu'un a-t-il trouvé une solution de contournement pour cela ? Ce n'est pas une bonne expérience de publier une bibliothèque open source et de devoir documenter la suppression de packages NPM spécifiques pour que les crochets commencent à fonctionner comme par magie ...

La solution autour de la suppression du module react du package lié ne fonctionne pas si ce package contient des tests qui nécessitent react (par exemple @testing-library/react ou @testing-library/react-hooks ), donc il on dirait que nous avons encore besoin d'une meilleure façon de gérer cela.

Ma demande se compose de deux parties. L'application Web principale et un module qui est chargé dynamiquement dans l'application Web. L'application Web et le module utilisent tous deux React 16.9.0.
Le module est chargé dans l'application Web à l'aide de React.lazy() et de l'instruction dynamique import().
Lorsque le module est chargé, l'erreur "Invalid hook call" est levée.

Dans mon cas, puisque l'application principale et le module sont construits séparément, ils ne se connaissent pas et vont avoir leur propre copie de réagir. J'ai essayé les suggestions suivantes trouvées dans le fil mais je n'ai pas résolu le problème.

  1. Ajout d'un alias dans le webpack.config du module qui pointe vers la réaction de l'application principale comme suggéré par apieceofbart .
    alias : {
    réagir : path.resolve('../../node_modules/react')
    }

  2. J'ai essayé de pointer les dépendances de réaction dans le package.json du module vers l'application principale.
    "dépendances": {
    "react-dom": " fichier:../common/node_modules/react-dom ",
    "react": " fichier:../common/node_modules/react "
    }

Je pense que react doit prendre en charge l'exécution de plusieurs copies lorsqu'il s'agit de modules chargés dynamiquement.

Sur la base de certaines des réponses ci-dessus, voici ce qui a fonctionné pour moi :

  1. Ajouté ce qui suit à config/webpack.config.js
externals: {
  react: {
    root: 'React',
    commonjs2: 'react',
    commonjs: 'react',
    amd: 'react'
  },
  'react-dom': {
    root: 'ReactDOM',
    commonjs2: 'react-dom',
    commonjs: 'react-dom',
    amd: 'react-dom'
  }
}
  1. Modifié package.json
"devDependencies" : {
  ...
  "react": "^16.9.0",
  "react-dom": "^16.9.0",
}
"peerDependencies": {
  "react": "^16.9.0",
  "react-dom": "^16.9.0"
}
  1. Modifié public/index.html
<head>
  <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
...

Après cela, j'ai pu exécuter des crochets dans ma bibliothèque en utilisant React chargé à partir de CDN, tandis que Jest chargeait toujours la copie de réaction à partir de node_modules (installé à partir de devDependencies).

J'espère que ça t'as aidé

J'ai rencontré ce problème lorsque j'essaie de changer mon composant d'un composant fonctionnel à un composant classfull et j'obtiens également cette erreur. Voici donc ma solution concernant cette erreur, j'espère que cela vous aidera également dans votre cas.

essayez d'utiliser un composant d'ordre supérieur dans ce cas

importer React depuis 'react' ;
importer les PropTypes à partir de 'prop-types' ;
importer { withStyles } de '@material-ui/styles' ;
importer le bouton de '@material-ui/core/Button' ;

styles constants = thème => ({
racine: {
arrière-plan: 'dégradé linéaire (45deg, #FE6B8B 30%, #FF8E53 90%)',
bordure : 0,
rayon de bordure : 3,
boxShadow : '0 3px 5px 2px rgba(255, 105, 135, .3)',
Couleur blanche',
taille : 48,
rembourrage : '0 30px',
},
});

class HigherOrderComponent étend React.Component {

rendre(){
const { classes } = this.props;
retourner (
Composant d'ordre supérieur
);
}
}

HigherOrderComponent.propTypes = {
classes : PropTypes.object.isRequired,
} ;

exporter par défaut withStyles(styles)(HigherOrderComponent);

J'utilise Yarn et j'ai résolu ce problème en forçant la résolution dans mon package.json :

  "resolutions": {
    "**/react": "16.7.0-alpha.2",
    "**/react-dom": "16.7.0-alpha.2"
  },

Avez-vous ajouté le package Parent ou Enfant ?

Sur la base de certaines des réponses ci-dessus, voici ce qui a fonctionné pour moi :

  1. Ajouté ce qui suit à config/webpack.config.js
externals: {
  react: {
    root: 'React',
    commonjs2: 'react',
    commonjs: 'react',
    amd: 'react'
  },
  'react-dom': {
    root: 'ReactDOM',
    commonjs2: 'react-dom',
    commonjs: 'react-dom',
    amd: 'react-dom'
  }
}
  1. Modifié package.json
"devDependencies" : {
  ...
  "react": "^16.9.0",
  "react-dom": "^16.9.0",
}
"peerDependencies": {
  "react": "^16.9.0",
  "react-dom": "^16.9.0"
}
  1. Modifié public/index.html
<head>
  <script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
  <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
...

Après cela, j'ai pu exécuter des crochets dans ma bibliothèque en utilisant React chargé à partir de CDN, tandis que Jest chargeait toujours la copie de réaction à partir de node_modules (installé à partir de devDependencies).

J'espère que ça t'as aidé

Aucune offense, mais il est inquiétant que des solutions comme celle-ci doivent être suivies. J'ai essayé de résoudre ce bogue ces derniers jours sans compter sur de tels hacks.

Je travaille sur une bibliothèque réutilisable qui contient des composants utilisant des crochets. Je dois les tester dans des projets réels avant de les publier. La seule solution pour cela est d'utiliser yarn|npm link . Je regroupe la bibliothèque à l'aide de rollup et je peux vérifier que le bundle ne contient pas de version de react. Lorsque je regroupe (webpack) l'application qui utilise la bibliothèque, le bogue/problème apparaît. Cela se produit également pour les applications nues create-react-app et next.js . Les deux frameworks utilisent webpack en arrière-plan.

Quelqu'un a-t-il déjà trouvé une solution durable ?

En abandonnant complètement npm|yarn link , j'ai pu résoudre le problème. Au lieu de cela, j'utilise cette jolie bibliothèque, qui est indépendante de la structure de votre projet. Cela vous permet également de continuer à utiliser webpack comme bundler, vous n'avez donc pas à déclarer _react_ et _react-dom_ en tant que external ou alias . Malheureusement, il introduit de nouveaux répertoires et verrouille des fichiers dans le projet, mais bon, cela fonctionne... localement et même à l'intérieur de nos conteneurs Docker.

Peut-être que ce sera à la liste un peu utile:

Lien

@GabrielBB merci, ça marche pour moi

@ dmart914 merci ! Jusqu'à présent, la seule solution de contournement qui fonctionne pour moi :)

Obtient actuellement l'avertissement React Invalid Hook Call lors de l'utilisation d'une configuration minimale et simple.

Ce composant de fonction :

  1. Utilise la même version pour React et ReactDOM.
  2. Suit les règles des crochets.
  3. N'a qu'une seule copie de React.

__Dépendances__
[email protected]
[email protected]
[email protected]
[email protected]

Et exécuter webpack test.js -o main.js pour construire.

Je m'attends à ce que ce fichier:

  • Rendez la boîte.

    • Mettez le débogueur en pause avant d'appeler React.useState .

    • Créez un booléen test et mettez à jour le rappel updateTest .

    • Lève l'erreur React.

    • Lors du rendu, effectuez les rappels React.useEffect .

    • Lève l'erreur React.

Est-ce que je fais quelque chose de mal ou y a-t-il autre chose qui se passe ?

// test.js
import React, { createElement as el } from 'react';
import ReactDOM from 'react-dom'; 

function Item() {
  debugger;
  const [test, updateTest] = React.useState(false); // Throws React error.

  React.useEffect(function checkTest() { // Throws React error.
    console.log("checking test", test);
  }, [test]);

  React.useEffect(function tester() { // Throws React error.
    if (!test) {
      setTimeout(() => {
        console.log("changing value for test");
        updateTest(true);
      }, 1000);
    }
  }, [test]);

  return el('div', {style: {width: '300px', height: '300px', 'background-color': 'green', border: '1px solid red'}});
}

function render() {
  let root = document.querySelector('#primary');
  if (!root) {
    root = document.createElement('div');
    document.body.appendChild(root);
  }

  ReactDOM.render(Item(), root);
}

render();

Vous avez oublié de créer un élément. Vous appelez Item() manière synchrone avant d'atteindre l'appel ReactDOM.render . Vous devez passer el(Item) .

Vrai! Merci pour l'info.

Suis dans une situation similaire à certains des autres commentateurs. J'utilise webpack pour transpiler certains composants de réaction (dont certains utilisent des crochets) et placer le code transpilé dans un dossier lib . J'ai ajouté réagir au champ externals de la configuration du webpack afin qu'il ne soit pas associé au code du composant. Je voudrais utiliser ces composants dans deux projets distincts - ces composants sont communs entre eux et nous aimerions donc les développer en un seul endroit et que les mises à jour soient reflétées dans les deux applications.

Si la dépendance est ajoutée à l'aide common-components: file:../../common-components/lib dans package.json, les composants se chargent parfaitement, mais l'exécution de webpack ne met pas à jour les composants immédiatement - à la place, je dois exécuter yarn upgrade common-components puis redémarrer le serveur de développement.

Si la dépendance est ajoutée à l'aide common-components: link:../../common-components/lib , la réexécution de Webpack mettra à jour les fichiers dans node_modules de l'application principale (car elle utilise maintenant un lien symbolique), mais j'obtiens l'erreur ci-dessus de plusieurs instances de réagir. Je suppose qu'il utilise maintenant la version de réaction dans le dossier common-components/node_modules .

Existe-t-il un moyen d'utiliser des liens symboliques (c'est-à-dire common-components: link:../../common-components/lib ), tout en s'assurant que les composants liés utilisent la réaction trouvée dans le dossier node_modules de l'application principale ? Étant donné que je prévois d'utiliser ces composants dans les deux applications, je ne peux pas lier le package de réaction de l'un d'eux à la bibliothèque de composants communs et je voudrais éviter de lier les réactions des applications principales à celle utilisée dans le package de composants communs. J'ai vu des commentaires faisant référence au champ webpack resolve qui semble prometteur mais je n'arrive pas à le faire fonctionner. Toute aide serait grandement appréciée!

edit : pour toute personne intéressée par notre cas d'utilisation, nous avons fini par changer l'étape de construction pour simplement copier les fichiers dans les deux projets dans lesquels ils sont nécessaires, et éviter complètement de transpiler.

Une solution rapide serait de ne pas publier le package, mais simplement de le pousser vers github et de l'importer dans votre projet en utilisant yarn add <git-url> .

Une solution rapide serait de ne pas publier le package, mais simplement de le pousser vers github et de l'importer dans votre projet en utilisant yarn add <git-url> .

La raison pour laquelle beaucoup d'entre nous utilisent les chemins relatifs des liens npm et des packages npm est de développer et de tester le code sans avoir à publier les modifications apportées à NPM ou GitHub avant de savoir que cela fonctionnera.

Nous avons rencontré ce problème lié à https://github.com/facebook/react/issues/13972#issuecomment -447599035 en ce sens que je pense que cela peut également être causé par un serveur Webpack'd Node. Notre cas d'utilisation était un test d'intégration exécuté dans Jest qui exécutait webpack() par programme pour construire le serveur avant d'exécuter les tests. Le problème, je crois, est lié à la façon dont l'ESM et le CJS peuvent exister en même temps.

Prenez cet exemple par exemple :

// node express server, doing server-rendering
import React from 'react';
import { ApolloProvider } from '@apollo/react-common';
import { renderToStringWithData } from '@apollo/react-ssr';

res.send(await renderToStringWithData(<ApolloProvider><App /></ApolloProvider>)

Ce que je vois lors d'une session de débogage, c'est que nous pouvons obtenir deux instances différentes de React dans la version compilée de ce fichier :

_react: {Children, ...}
_react2: {default: {Children, ...}


_react provient de l'ESM import React from 'react' dans ce fichier
_react2 provient du CJS var _react = _interopRequireDefault(require("react")); depuis node_modules/@apollo/react-ssr/lib/react-ssr.cjs.js

Je crois que cela a fait que la référence à React n'était pas égale aux deux endroits (fichier de rendu du serveur et à l'intérieur du bundle @apollo/react-ssr ) et a donc provoqué l'erreur.

Nous avons constaté que cela était probablement dû à l'utilisation programmatique de webpack() depuis le test, et nous avons refactorisé ces tests pour en faire des tests de bout en bout. La leçon étant pour nous que si le problème se produit uniquement dans le code de test, vous pouvez avoir des tests trop compliqués.

J'ai réussi à le résoudre avec du fil:

cd à myApp/node_modules/react et yarn link

puis dans votre bibliothèque, exécutez yarn link react

Maintenant, votre bibliothèque utilise exactement la même version de réaction que votre application principale

J'ai essayé de définir réagir en tant que dépendance de pair dans ma bibliothèque, mais la bibliothèque ne se construirait pas

Comment résoudre ce problème en utilisant create-react-app sans éjecter ou passer à yarn ?

Vous pouvez simplement utiliser exactement la même technique en utilisant le lien npm. Aucune éjection nécessaire.

Lier react n'est pas la meilleure idée lorsque vous travaillez sur plusieurs projets avec différentes versions.

@woles vous avez tout à fait raison mais dans mon cas, cela résout mon problème de "crochets". J'espère que les développeurs de réaction trouveront une meilleure solution

Salut,
J'ai corrigé ce bogue après des heures en réalisant que j'avais accidentellement utilisé le composant à l'intérieur du routeur de réaction.

Mon application fonctionnait mais dans un composant, je ne pouvais pas du tout ajouter useState. la raison en est que j'ai utilisé le composant à l'intérieur de la méthode de rendu des routeurs de réaction sans la fonction d'ordre supérieur comme celle-ci:
<Route exact path="/path" render={ ComponentCausingTheErrorMesage }/>
passer à
<Route exact path="/path" component={ ComponentNowWorkingAgain }/>
me l'a réparé

J'utilisais npm link entre une application et un module sur lequel je travaillais activement, et j'ai dû le réparer en liant les react et react-dom de l'application au module, puis en liant le module à l'application :

dans l'application :

  1. cd node_modules/react && npm link
  2. idem pour react-dom

dans le module :

  1. npm link react && npm link react-dom
  2. npm link

dans l'application :

  1. npm link [module-name]

J'espère que cela aide quelqu'un

Nous avions des crochets qui fonctionnaient côté client, mais nous rencontrions cette erreur sur SSR. Mon collègue l'a résolu avec ce qui suit dans notre configuration webpack côté serveur :

const nodeExternals = require('webpack-node-externals');

const serverConfig = () => {
  // lots of config, then:
  externals: [
    nodeExternals({
      modulesFromFile: true,
    }),
  ],
}

J'ai réussi à le résoudre avec du fil:

cd à myApp/node_modules/react et yarn link

puis dans votre bibliothèque, exécutez yarn link react

Maintenant, votre bibliothèque utilise exactement la même version de réaction que votre application principale

J'ai essayé de définir réagir en tant que dépendance de pair dans ma bibliothèque, mais la bibliothèque ne se construirait pas

Cela fonctionne tout simplement magnifique

Je viens de rencontrer ce problème, lors de l'utilisation d'électron-webpack, de réaction et de matériel-ui en même temps. Lorsque j'essaie d'utiliser quoi que ce soit de material-ui - j'obtiens cette erreur (par exemple, essayez d'utiliser un

Salut ZVER3D, essayez de lire mon commentaire précédent. J'espère que ça aide!

J'utilisais npm link entre une application et un module sur lequel je travaillais activement, et j'ai dû le réparer en liant les react et react-dom de l'application au module, puis en liant le module à l'application :

dans l'application :

1. `cd node_modules/react && npm link`

2. same for `react-dom`

dans le module :

1. `npm link react && npm link react-dom`

2. `npm link`

dans l'application :

1. `npm link [module-name]`

J'espère que cela aide quelqu'un

Doux bébé Moïse, cela m'a beaucoup aidé. Je n'ai même pas considéré que le problème était les différentes versions de réagir !! Je construis localement un composant à publier sur NPM mais j'ai un projet séparé pour le tester localement, en utilisant le lien npm. De toute évidence (maintenant), ils utilisent tous les deux des versions différentes de réagir. Oh !

Salut ZVER3D, essayez de lire mon commentaire précédent. J'espère que ça aide!

Merci de m'avoir orienté dans la bonne direction. Une autre solution consistait à ajouter la bibliothèque ui, que j'utilise dans "whiteListedModules". Le seul problème serait que vous deviez le faire pour tous les modules nécessitant une réaction pour être compilés.
Donc, dans package.json j'ai écrit ceci:

"electronWebpack": {
    "whiteListedModules": [
      "@material-ui/core",
      "@material-ui/icons"
    ]
  }

Je développe une application React en utilisant l'approche monorepo. J'ai une application principale ( brush ) et un composant de bibliothèque de réaction ( react-gbajs ).

Ainsi, lorsque j'essaie de rendre mon composant react-gbajs , j'ai cette erreur à propos de plusieurs instances de React. Si je copie et colle le même code sur brush , je n'ai aucun problème.
J'ai suivi de nombreuses approches pour résoudre ce problème, mais aucune d'entre elles ne l'a résolu (modifier la construction sur Webpack, l'espace de travail de Yarn, le lien npm ...)

J'ai essayé de déboguer pour vérifier si j'ai vraiment deux copies de React (en utilisant console.log(window.React1 === window.React2) de la doc de React), mais cela s'évalue comme true !
(une TRÈS MAUVAISE solution de contournement que j'utilise maintenant consiste à passer les crochets comme prop : <GBAEmulator useEffect={useEffect} /> ... mais je ne veux vraiment pas le fusionner)

Quelqu'un a une idée pour y remédier ?

Mon projet est open source et j'ajoute ce nouveau composant de bibliothèque de réaction à cette branche : https://github.com/macabeus/klo-gba.js/blob/ac18f4d42b122c333622f502947135c2de217ce2/react-gbajs/src/index.js#L251 -L274

Salut tout le monde,

J'ai une application (myApp) qui utilise comme dépendance une bibliothèque personnalisée (myDepPackage). Les deux utilisent webpack comme outil de construction et bien sûr, j'avais la même erreur. Aucune des solutions ci-dessus n'a fonctionné pour moi. Ce qu'il a fait, c'est forcer webpack à NE PAS inclure de réaction dans le dernier paquet de la bibliothèque personnalisée (myDepPackage). La seule ligne de configuration que j'ai dû ajouter à la configuration du webpack (du myDepPackage) est la suivante :

externals: {
  react: "react",
},

Vous pouvez en savoir plus sur l'option "externals" ici : https://webpack.js.org/configuration/externals/#externals

@tsevdos Vraiment merci !!! ❤️
Il a résolu mon problème que j'ai dit au commentaire précédent.

Pour nous, le problème était que nous avions une application React intégrable qui était chargée dans la page à partir d'un shortcode WordPress et montée sur une div avec un ID aléatoire. Sur certaines pages, nous avons plusieurs applications intégrées et cela fonctionnait très bien jusqu'à ce que nous commencions à utiliser des crochets.

Il ne se plaindrait que sur les pages qui ont plusieurs applications intégrées, donc la solution consistait à mettre à jour le shortcode WP pour charger le script avec la construction une seule fois.

Cela semble simple et évident, mais c'était difficile à comprendre! Surtout parce qu'il faisait ça et fonctionnait bien jusqu'à ce que nous ajoutions des crochets.

Il est intéressant de noter que sur certaines pages, nous avons d'autres applications - différentes - que nous intégrons et qui utilisent également des crochets, et elles chargent également leur propre script/build avec React,... mais cela fonctionne très bien ! Le problème était quand c'était exactement la même version qui était chargée plus d'une fois et qu'ils utilisaient des hooks .

Ce qui a fonctionné pour moi était une combinaison de deux suggestions de ce fil de discussion.

Configuration du pack Web de l'application principale ( suggestion de @apieceofbart )

  resolve: {
    alias: {
      react: resolve('./node_modules/react')
    }
  }

Configuration du webpack de la dépendance ( suggestion de @tsevdos )

  externals:
    react: 'react'
  }

J'avais ce problème avec html-webpack-plugin et j'utilisais index.html comme un paramètre template à HtmlWebpackPlugin .

// webpack.config.js
plugins: [
   new HtmlWebpackPlugin({
      template: "./public/index.html"
   })
],
<!-- public/index.html -->
<html>
<head>
    <title>React App</title>
</head>
<body>
    <div id="root"></div>
    <script src="main.js"></script>
</body>

</html>

J'ai réalisé que le plugin injectait <script type="text/javascript" src="main.js"></script> juste après <div id="root"></div> .

Ainsi, lorsque j'ai ouvert l'outil de développement et que le code HTML généré ressemblait à ceci.

<html>
<head>
    <title>React App</title>
</head>
<body>
    <div id="root"></div>
    <script src="main.js"></script>
    <script type="text/javascript" src="main.js"></script> <!-- injected from html-webpack-plugin -->
</body>

</html>

Pour moi, cela causait Invalid Hook Call Warning .

J'ai pu supprimer l'avertissement en supprimant <script src="main.js"></script> comme ci-dessous.

<!-- public/index.html -->
<html>
<head>
    <title>React App</title>
</head>
<body>
    <div id="root"></div>
</body>

</html>

J'espère que cela aidera quelqu'un à la recherche d'une solution!

Sachez que les bibliothèques dépendantes de React peuvent également causer ces problèmes. Dans mon cas, j'utilisais différentes versions de @emotion/core et @emotion/styled .

https://github.com/emotion-js/emotion/issues/1470

Salut,

Une solution possible sans éjection consiste à mélanger la solution de configuration d'alias webpack avec les bibliothèques customize-cra et react -app-rewired . De cette façon, vous pouvez remplacer uniquement la configuration Webpack nécessaire pour résoudre le problème, en créant un fichier config-overrides.js avec :

const { override, addWebpackAlias } = require('customize-cra');
const path = require('path');

module.exports = override(
  addWebpackAlias({
    react: path.resolve(path.join(__dirname, './node_modules/react')),
  }),
);

J'ai eu ce problème sur un site Gatsby, j'ai exécuté npm install et mis à jour vers la dernière version de Gatsby et tout a été résolu

Si vous rencontrez un problème avec les tests de blagues en cours d'exécution yarn or npm test (comme moi) et que vous utilisez react-test-renderer , assurez-vous que react-test-renderer correspond à la même version de react vous utilisez.

Exemple:

// Package.json
{
  ...
    "react" : "16.8.3",
  ...
}

Courez yarn add [email protected]

J'ai une bibliothèque et j'ai vérifié toutes les versions de react et react-dom dans les projets lib et main. ils sont exactement les mêmes mais n'ont pas fonctionné.
Cependant, la solution @apieceofbart a fonctionné pour moi.

@apieceofbart , tu m'as sauvé la journée <3

Ce qui a fonctionné pour moi était une combinaison de deux suggestions de ce fil de discussion.

Configuration du pack Web de l'application principale ( suggestion de @apieceofbart )

  resolve: {
    alias: {
      react: resolve('./node_modules/react')
    }
  }

Configuration du webpack de la dépendance ( suggestion de @tsevdos )

  externals:
    react: 'react'
  }

Pareil ici. Je dois faire ces deux correctifs pour que cela fonctionne. Mon explication est que la deuxième configuration indique à la dépendance d'utiliser la réaction externe avec le nom 'react', et la première configuration pointe le nom 'react' vers le dossier 'node_modules/react' dans le référentiel principal. Par conséquent, les deux sont nécessaires pour faire fonctionner le pont de réaction.

Pourtant, il semble que pour certaines personnes, l'un d'eux suffit, ce que je ne comprends pas vraiment.

Ce qui a fonctionné pour moi était une combinaison de deux suggestions de ce fil de discussion.
Configuration du pack Web de l'application principale ( suggestion de @apieceofbart )

  resolve: {
    alias: {
      react: resolve('./node_modules/react')
    }
  }

Configuration du webpack de la dépendance ( suggestion de @tsevdos )

  externals:
    react: 'react'
  }

Pareil ici. Je dois faire ces deux correctifs pour que cela fonctionne. Mon explication est que la deuxième configuration indique à la dépendance d'utiliser la réaction externe avec le nom 'react', et la première configuration pointe le nom 'react' vers le dossier 'node_modules/react' dans le référentiel principal. Par conséquent, les deux sont nécessaires pour faire fonctionner le pont de réaction.

Pourtant, il semble que pour certaines personnes, l'un d'eux suffit, ce que je ne comprends pas vraiment.

Le deuxième élément est important !
S'il est ignoré, lors du processus de construction, la réaction sera exportée ensemble, car il s'agit d'une dépendance interne

beaucoup d'amour @apieceofbart !!!! J'étais sur le point de frapper mon bureau à travers le mur

Il n'y a donc toujours pas de solution de contournement pour les microservices. J'ai une application racine avec réaction qui nécessite dynamiquement des bundles avec une autre réaction. Nous ne pouvons pas simplement utiliser une version externe de react car il y a beaucoup d'équipes indépendantes avec leurs propres dépendances. Si nous les poussons à utiliser la même version externe, la plupart des projets planteront évidemment et il deviendra impossible de mettre à jour cette version car chaque projet dépendra de cette version.

Des idées?

Existe-t-il une solution pour utiliser les crochets de réaction avec le lien npm, qui ne nécessite pas d'éjection de l'ARC ?

@tschellenbach
vous pouvez utiliser craco pour écraser la configuration CRA sans éjecter.
https://github.com/gsoft-inc/craco

Grâce à @tsevdos , j'ai résolu mon problème et réalisé un tutoriel sur la création d'un package React : https://youtu.be/esyS87NfBOw

Je recevais ce problème et la solution Webpack ne s'appliquait pas car j'utilise plutôt le groupeur de colis. J'ai pu le réparer en spécifiant un alias dans le package.json de mon application principale qui ressemblait à ceci

    "alias": {
        "react": "./node_modules/react",
        "react-dom": "./node_modules/react-dom"
    },

Obtenir des problèmes en essayant d'utiliser mes composants React (écrits dans des crochets) dans une application électronique dans le même projet avec un package json différent. La structure du fichier ressemble à ceci :

- javascript
  - src
     - ComponentIWantToUse.tsx
      - package.json
- electron
   - src
     - IwantToUseItHere.tsx
      - package.json

Les deux package.json incluent react et react-dom dans package.json mais ce sont les mêmes versions et je ne le vois pas montrer deux installations de réaction lorsque je fais npm ls react . Des idées?

EDIT : la solution de @ewan-m a fonctionné !

J'ai donc rencontré un cas bizarre, je pense. Une bibliothèque tierce a malheureusement mélangé des composants fonctionnels et basés sur des classes. Mes composants dans ma base de code sont fonctionnels. Un composant basé sur une classe de la bibliothèque agit comme une mise en page qui rend mon composant en tant qu'enfant. Je pense que c'est ce qui déclenche l'erreur "Erreur : appel de crochet non valide". Comment dois-je contourner cela pour utiliser des crochets, dois-je convertir le mien en un composant de classe?

@GrandathePanda Mélanger les classes et les composants fonctionnels ne devrait pas avoir d'importance. Si une classe appelle une fonctionnelle, qui appelle un crochet, il n'y a pas de problème là-bas. La seule chose que vous ne pouvez pas faire est d'appeler un hook directement depuis la classe.

D'accord, @JeremyGrieshop alors j'ai encore des recherches à faire, si je rends sans utiliser le composant tiers, le rendu est correct, il y a donc un conflit entre cette bibliothèque et mon code. Si je devais deviner qu'ils utilisent une version de réaction différente, peut-être dans leur package.

D'accord, @JeremyGrieshop alors j'ai encore des recherches à faire, si je rends sans utiliser le composant tiers, le rendu est correct, il y a donc un conflit entre cette bibliothèque et mon code. Si je devais deviner qu'ils utilisent une version de réaction différente, peut-être dans leur package.

Bien, vérifiez npm ls react react-dom depuis votre application pour voir s'il existe plusieurs versions. Il est possible que la bibliothèque tierce ait une dépendance avec une version spécifique.

@JeremyGrieshop Il semble donc que mon application utilise 16.12.0 pour réagir et dom et le tiers (elastic search-ui) utilise 16.8.0 pour réagir et dom. Si j'ai raison, le problème est que, puisque ma bibliothèque tierce 16.8.0 rend le composant créé avec 16.12.0, cela causera le problème ? Il s'agit également d'un lerna monorepo, ce qui complique potentiellement encore plus la situation après avoir lu tous les commentaires ci-dessus. Le problème provient d'un crochet useStyles créé dans materialui, ils fournissent un withStyles hoc pour une compatibilité descendante et je pense qu'en attendant, je vais emprunter cette voie. Tous les changements apportés à webpack et/ou au package json mentionnés ci-dessus semblent vraiment être un pansement qui est plus susceptible de se casser que de simplement aller avec un hoc classique en attendant, tandis que les crochets trouvent comment mûrir face à tant de problèmes d'implémentation différents.

@GrandathePanda IMHO, vos options sont de (1) demander au tiers de mettre à jour sa dépendance de réaction à 16.12, ou de lui faire décider si l'avoir comme peerDependency est plus approprié qu'une dépendance; (2) Utilisez 16.8 dans votre application afin qu'ils partagent les mêmes versions de bibliothèques ; (3) Éliminer leur copie de réagir avec :

rimraf node_modules/search-ui/node_modules/react && rimraf node_modules/search-ui/node_modules/react-dom

La commande ci-dessus peut être placée dans un "prebuild" et "prestart" sous la partie "scripts" de votre package.json (ce que je fais actuellement). L'inconvénient de (3), je suppose, est s'ils utilisent quoi que ce soit obsolète entre 16.8 et 16.12.

Salut tout le monde,

J'ai une application (myApp) qui utilise comme dépendance une bibliothèque personnalisée (myDepPackage). Les deux utilisent webpack comme outil de construction et bien sûr, j'avais la même erreur. Aucune des solutions ci-dessus n'a fonctionné pour moi. Ce qu'il a fait, c'est forcer webpack à NE PAS inclure de réaction dans le dernier paquet de la bibliothèque personnalisée (myDepPackage). La seule ligne de configuration que j'ai dû ajouter à la configuration du webpack (du myDepPackage) est la suivante :

externals: {
  react: "react",
},

Vous pouvez en savoir plus sur l'option "externals" ici : https://webpack.js.org/configuration/externals/#externals

@tsevdos je t'aime. Vous venez de mettre fin à quelques jours de tracas intenses. Merci.

Salut tout le monde,

J'essaie d'utiliser un crochet dans un composant, ce composant doit être exporté depuis gatsby-browser.js .

Quel est le comportement actuel ?

J'obtiens cette erreur :

Rejet non géré (erreur) : appel de crochet non valide. Les crochets ne peuvent être appelés qu'à l'intérieur du corps d'un composant de fonction. Cela peut se produire pour l'une des raisons suivantes :

  1. Vous pouvez avoir des versions incompatibles de React et du moteur de rendu (comme React DOM)
  2. Vous pourriez enfreindre les règles des crochets
  3. Vous pouvez avoir plusieurs copies de React dans la même application
    Voir https://fb.me/react-invalid-hook-call pour des conseils sur la façon de déboguer et de résoudre ce problème.

Ceci est un exemple de code :

import React from 'react';
import PropTypes from 'prop-types';
import { Provider } from 'react-redux';

import configureStore from './src/utils/configure-store';
import { useApiResources } from './src/hooks/use-api-resources';

const RootWrapper = ({ element }) => {
  const resources = useApiResources();
  const store = configureStore();
  return <Provider store={store}>{element}</Provider>;
};

RootWrapper.propTypes = {
  element: PropTypes.node.isRequired,
};

export default RootWrapper;

Quel est le comportement attendu ?

Hook doit s'exécuter sans erreur, ou des messages d'erreur utiles doivent être fournis.

Les versions des dépendances de réaction et de réaction-dom sont 16.12.0

@ leejh3224 merci beaucoup mec ! après des heures de recherche, j'ai trouvé cette réponse, cela a résolu mon problème.
Je viens de changer la configuration HtmlWebpackPlugin de
inject: true à inject: 'head' et les erreurs de réaction minifiées ont disparu.

J'ai créé une question stackoverflow avec mon expérience d'essayer de faire fonctionner cela. Serait-il possible, pour ceux qui ont réussi à le faire fonctionner, d'y jeter un coup d'œil et de donner quelques conseils ?

Je porte une application jquery sur React. J'ai un utilitaire pour exposer les composants React dans jQuery appelé asJqueryPlugin . Voici le fichier :

import React from 'react'
import ReactDOM from 'react-dom'

/**
 * A way to render React components with props easily with jQuery
 *
 * ## Register the React Component
 *
 * In your React Component file, register the component with jQuery using `asJqueryPlugin`
 * ```
 * const Greeting = ({ person }) => <div>Hello {person}</div>
 * asJqueryPlugin('Greeting', Greeting, { person: "Bob" })
 * ```
 *
 * ## Rendering, Selecting and Updating Props with jQuery
 *
 * Select an element and render using the `react` function
 * ```
 * $('#greeting').react('Greeting', { person: 'Frank' })
 * ```
 */

window.reactRegistry = window.reactRegistry || {}

// This is how React components register themselves as available within jQuery
export default function asJqueryPlugin(componentName, Component) {
  window.reactRegistry[componentName] = { Component }
}

if (typeof window.$ !== 'undefined') {
  ;(function($) {
    // Add the plugin function jQuery
    $.fn.react = function renderReactIntoElements(componentName, props) {
      this.each(function render() {
        const entry = window.reactRegistry[componentName || $(this).data('react')]
        if (!entry) throw Error(`${componentName} component is not registered.`)
        ReactDOM.render(<entry.Component {...props} />, this)
      })
      return this
    }
  })(window.$)
}

L'application a de nombreux points d'entrée dans Webpack, et environ 3-4 composants utilisent cette technique maintenant. Lorsque les composants sont regroupés dans différents ensembles de points d'entrée, je pense que c'est à ce moment-là que le problème se produit.

Donc, si j'ai deux points d'entrée dans Webpack :

entry: {
      foo: './assets/js/foo',
      bar: './assets/js/bar'
}

Ensuite, dans chacun de ces fichiers, nous configurons un composant exposé (chacun utilisant des crochets) :

// foo.js
import React from 'react'
import asJqueryPlugin from '../utils/asJqueryPlugin'
const Foo = () => {
  const ref = useRef()
  return <div ref={ref}>Foo</div>
}
asJqueryPlugin('Foo', Foo)

// bar.js
... same stuff but with Bar component

Maintenant, si j'inclus les deux entrées sur la même page et que j'essaie de rendre les deux composants via le plugin jquery...

<script src="/bundles/foo.js" />
<script src="/bundles/bar.js" />
<script>
    $('#foo-container').react('Foo')
    $('#bar-container').react('Bar')
</script>

... J'obtiens cette erreur de crochets.

Je ne sais pas si cela aide la conversation ou non, mais montre au moins un cas d'utilisation de la façon dont un développeur (discutablement) sain d'esprit pourrait se retrouver dans une situation avec plusieurs instances de réaction.

Cela m'a aidé - https://github.com/facebook/react/issues/13991#issuecomment -554928373
Mais j'ai également dû supprimer react et react-dom des dépendances et les déplacer vers des dépendances homologues et désinstaller et réinstaller les modules de nœud.

Salut,
J'ai lu la conversation et de nombreux messages sur le Web et je suis toujours coincé avec l'erreur plusieurs instances de réaction.
Je pousse ce repo pour reproduire le bug : https://github.com/jeromelegrand/dooliz-lib
J'espère que quelqu'un pourra m'aider.
Merci.

Je suis confronté à ce problème et je n'arrive nulle part avec les solutions ci-dessus.
En bref: je suis très certain que je n'ai qu'une seule version de réaction en cours d'exécution, et j'obtiens l'erreur en utilisant react-bootstrap, qui n'utilise probablement pas de mauvais crochets, car personne d'autre n'a de problèmes.

Cette erreur se produit sur un backend node.js pour moi.

__Ce que j'ai vérifié autour des versions de réaction__

J'ai une configuration de fil avec des espaces de travail, yarn list react ou yarn list react-dom ne montre qu'une seule instance.

J'ai imprimé require cache pour voir ce qui a été importé :

for(var key in require.cache) {
    if(key.indexOf("react") !== -1 && key.indexOf("index") !== -1) {
        console.log(key);
    }
}

Je l'exécute juste avant de rendre quelque chose à partir de react-bootstrap, ce qui provoque l'erreur de crochet invalide pour moi, et il se connecte :

C:\web\resourceful\daCore\node_modules\react-dom\index.js
C:\web\resourceful\daCore\node_modules\react\index.js
C:\web\resourceful\daCore\node_modules\react-router-dom\index.js
C:\web\resourceful\daCore\node_modules\react-router-dom\node_modules\react-router\index.js
C:\web\resourceful\daCore\node_modules\react-is\index.js
C:\web\resourceful\daCore\node_modules\mini-create-react-context\dist\cjs\index.js
C:\web\resourceful\daCore\node_modules\react-router\index.js
C:\web\resourceful\daCore\node_modules\@fortawesome\react-fontawesome\index.js
C:\web\resourceful\daCore\node_modules\@tinymce\tinymce-react\lib\cjs\main\ts\index.js

Ce qui semble confirmer qu'il n'y a qu'une seule version de réaction chargée.

Enfin, j'ai ajouté ceci à node_modules/react-dom/index.js

console.log("React DOM daCore");
global['React1'] = require('react');

Et ceci à node_modules/react-router-dom/cjs/Form.js

require('react-dom');
global['React2'] = require('react');
console.log('#TEST '+(global['React1'] === global['React2']? 'SAME' : 'NOT SAME'));

Qui imprime SAME

Une idée de ce que cela peut être d'autre?
Je publierai également ceci sur le dépôt react-bootstrap.

Je suis donc à peu près sûr que le fait d'avoir deux instances de React n'est pas le problème ici. Je pense que le problème est quand il y a deux _roots_ de réaction. Appelez-vous ReactDOM.render() plusieurs fois dans différentes parties de la page ? Si c'est le cas, je pense que cela peut causer le problème. Je pense que les crochets "appartiennent" à une "racine" particulière et se cassent lorsqu'il y en a plusieurs et que les deux faisceaux partagent un code commun. Je suppose ici...

... Je pense que le problème est quand il y a deux _roots_ de réaction. Appelez-vous ReactDOM.render() plusieurs fois dans différentes parties de la page ?

Merci @timkindberg, cela m'a aidé à le résoudre. J'ai réalisé que j'utilisais react-tree-walker pour faire un rendu initial et récupérer les données requises avant de faire le rendu final avec ReactDOMServer.renderToString

La suppression rapide de l'utilisation de ce package a supprimé l'erreur, et j'ai maintenant la même chose qui fonctionne avec react-ssr-prepass , qui est en fait maintenant recommandé sur la page readme de react-tree-walker

Il s'agissait donc bien de deux appels ReactDOM.render ! Pour l'instant, cette configuration avec react-ssr-prepass fonctionne pour moi, et lorsque Suspense atterrit dans react-dom/server, je peux passer à cela

J'utilise react-compare-image https://github.com/junkboy0315/react-compare-image dans mon projet Gutenberg mais j'ai ce problème étrange bien que tout fonctionne chaque fois que je supprime le composant ReactCompareImage de la fonction de sauvegarde. La fonction d'édition fonctionne parfaitement mais la sauvegarde ne fonctionne pas.

Je suis passé par https://reactjs.org/warnings/invalid-hook-call-warning.html et je ne pense pas avoir l'un de ces problèmes.

Voici le fichier de fonction de sauvegarde complet :

```importer l'inspecteur depuis "./inspecteur" ;
importer { Fragment } de "réagir" ;
importer ReactCompareImage à partir de "react-compare-image" ;

/**

  • Dépendances WordPress
    */
    const {__} = wp.i18n ;

const save = ({className, attributs}) => {

const {
    paddingTop,
    paddingRight,
    paddingBottom,
    paddingLeft,

    marginTop,
    marginRight,
    marginBottom,
    marginLeft,

    border,
    borderColor,
    borderType,
    background,

    backgroundImage,
    gradient,

    dividerColor,
    buttonColor,

    direction,

    beforeImage,
    beforeLabel,
    afterImage,
    afterLabel,

} = attributes;

const style = {
    "padding": `${paddingTop}px ${paddingRight}px ${paddingBottom}px ${paddingLeft}px`,
    "margin": `${marginTop}px ${marginRight}px ${marginBottom}px ${marginLeft}px`,
    "border": `${border}px ${borderType} ${borderColor}`,
    "background": background
};

return(
    <Fragment>
        <ReactCompareImage
            leftImage={beforeImage.url}
            leftImageLabel={beforeLabel}
            rightImage={afterImage.url}
            rightImageLabel={afterLabel}
            vertical={'vertical' === direction}
            sliderLineColor={dividerColor}
        />
    </Fragment>
);

} ;

exporter la sauvegarde par défaut ;
```
Screenshot 2020-02-19 at 4 11 52 PM

Je rencontre également ce problème. J'ai un récapitulatif publié sur SO : https://stackoverflow.com/questions/60331304/next-js-with-typescript-invalid-hook-call-hooks-can-only-be-called-inside-of-t

J'ai aussi un exemple reproductible minimal : https://github.com/coler-j/shopify_playground

Mon application principale est une application create-react (non éjectée) qui importait une bibliothèque partagée qui utilisait également React. J'ai pu résoudre ce problème en:

Utilisation de Rollup pour empaqueter la bibliothèque au lieu de webpack
Pour une raison que je n'ai pas encore déterminée, l'utilisation d'externals n'a pas supprimé React du bundle de bibliothèques.

rollup-config.js

export default [
  {
    input: 'src/index.js',
    output: {
      file: pkg.main,
      format: 'cjs',
      sourcemap: true,
    },
    plugins: [external(), babel(), resolve(), commonjs(), svgr()],
  },
  {
    input: 'src/index.js',
    output: {
      file: pkg.module,
      format: 'es',
      sourcemap: true,
    },
    plugins: [
      alias({
        entries: [{ find: '<strong i="12">@components</strong>', replacement: 'src/components' }],
      }),
      external(),
      babel(),
      svgr(),
    ],
  },
]

Installer craco et l'utiliser pour modifier le pack Web de l'application principale
craco.config.js

const path = require('path')

module.exports = {
  webpack: {
    alias: {
      react: path.resolve(__dirname, './node_modules/react'),
    },
  },
}

Merci à @arminyahya de m'avoir indiqué craco.

J'essaie d'utiliser des crochets lors du chargement de la réaction d'un cdn. Cet exemple (c'est la page html entière) donne l'erreur Hooks can only be called inside of the body of a function component lorsque Example() est appelé. J'ai tout supprimé, même ReactDOM, il est donc difficile d'imaginer que je pourrais avoir plusieurs copies de React. Est-ce tout simplement impossible ?

<!DOCTYPE html>
<html>

<head>
  <script crossorigin src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>

</body>
  <script type="text/babel">
    function Example() {
      let [count, setCount] = React.useState(0);
      return ( <h1>Hello</h1> );
    };

  Example();
  </script>
</body>

</html>

@samkamin C'est parce que vous avez des racines de réaction ZÉRO. Vous devez rendre votre application. Cependant, cela reste une bonne confirmation que les crochets reposent sur (et sont couplés à) une racine de réaction.

<html>
<head>
  <script crossorigin src="https://unpkg.com/[email protected]/umd/react.development.js"></script>
  <script crossorigin src="https://unpkg.com/[email protected]/umd/react-dom.development.js"></script>
  <script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
</body>
  <div id="root"></div>
  <script type="text/babel">
    function Example() {
      let [count, setCount] = React.useState(0);
      return ( <h1>Hello</h1> );
    };

    ReactDOM.render(<Example />, document.getElementById('root'))
  </script>
</body>
</html>

Merci! Ce n'était en fait pas l'absence d'une racine de réaction - je l'ai simplement supprimée au cours de la simplification de l'erreur autant que possible - mais quelque chose d'aussi stupide : au lieu de <Example /> , j'écrivais simplement Example() . Pas du tout la même chose. Merci encore.

Rien ne semble fonctionner pour moi. Je crée un composant à partager et à utiliser dans d'autres projets, mais le test local à partir d'un autre projet ne fonctionne pas. J'utilise Hooks avec react 16.13.0.

webpack.config.js

module.exports = {
  entry: ENTRY,
  output: {
    library: LIBRARY_NAME,
    path: path.resolve(__dirname, OUTPUT_DIR),
    filename: OUTPUT_FILENAME,
    libraryTarget: 'commonjs2',
  },
  module: {
    rules: [
      {
        test: /\.(js|tsx)$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      },
      {
        test: /\.tsx?$/,
        exclude: /node_modules/,
        use: 'ts-loader',
      },
    ],
  },
  resolve: {
    alias: {
      '<strong i="7">@src</strong>': path.resolve(__dirname, './src'),
      '<strong i="8">@components</strong>': path.resolve(__dirname, './src/components'),
      '<strong i="9">@core</strong>': path.resolve(__dirname, './src/core'),
      react: path.resolve(__dirname, './node_modules/react'),
      'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
    },
    extensions: ['.js', '.json', '.tsx', '.ts'],
  },
  externals: {
    react: 'react',
  },
  target: 'node',
  plugins: [
    new HtmlWebPackPlugin({
      template: './tests/index.html',
      filename: 'index.html',
    }),
  ]}

Aucune suggestion? J'ai testé toutes les suggestions des anciennes discussions.
Merci! :sourire:

J'ai déclaré un Settings.js comme suit:

import React, {useState} from 'react';

import {
    View,
    Text,
    Switch
} from 'react-native';

export function Settings(props) {
    const [rememberPin, setRememberPin] = useState(false);
    let {changeView, header} = props;


    const toggleRememberPin = (value) => {
        setRememberPin(value);
    };

    return (
            <View>
                    <Text>Remember PIN:</Text>
                    <Switch
                        onValueChange={toggleRememberPin}
                        value={rememberPin}
                        ios_backgroundColor="#aeaeae"
                        />
            </View>
    );
}

export default {Settings};

Je l'importe et l'utilise dans App.js comme suit :

import React, {Component} from 'react';
import {
    SafeAreaView,
    StyleSheet,
    View,
    Text,
    TouchableOpacity,
    Dimensions,
    ScrollView,
    Switch
} from 'react-native';

import Colors from './src/assets/Colors';
import {Settings} from './src/components/Settings';
...

export default class App extends Component {
    constructor(props) {
        super(props);
        this.state = {viewsStack: this.viewsStack};
    }

    viewsStack = {
        SplashScreen: false,
        BindingInstructions: false,
        PinPad: false,
        Qr: false,
        Dashboard: false,
        Authorizations: false,
        Settings: true,
        Browsers: false,
        TransmitSDK: false,
        OTP: false,
    };

    changeView = (newView) => {
        let {viewsStack} = this.state;
        for (let key of Object.keys(viewsStack)) {
            viewsStack[key] = false;
        }
        viewsStack[newView] = true;
        this.setState(viewsStack);
    };

    render() {
        let {viewsStack} = this.state;
        return (
            <SafeAreaView style={styles.safeAreaView}>
                {viewsStack.SplashScreen && (splashScreen())}
                {viewsStack.BindingInstructions && (bindingInstructions({changeView: this.changeView}))}
                {viewsStack.PinPad && (pinPad({message: 'Inserisci un nuovo PIN', changeView: this.changeView}))}
                {viewsStack.Qr && (qr({header: 'QR Binding', message: 'Scansiona il QR dalla tua dashboard\noppure\ninserisci il codice manualmente.', changeView: this.changeView}))}
                {viewsStack.Dashboard && (dashboard({header: 'Profilo Utente', changeView: this.changeView}))}
                {viewsStack.Authorizations && (authorizations({header: 'Autorizzazioni', authorizations: [1, 2, 3, 4, 5, 6], changeView: this.changeView}))}
                {viewsStack.Settings && (Settings({header: 'Impostazioni', changeView: this.changeView}))}
            </SafeAreaView>
        );
    }
};
...

Mais j'obtiens :

Screenshot 2020-02-27 at 22 27 01

J'utilise:

"react": "16.9.0",
"react-native": "0.61.5"

Qu'est-ce qui ne va pas?

Vous appelez votre composant Settings en tant que fonction et non en tant que composant de fonction.

<Settings header='Impostazioni' changeView={this.changeView} />

Les crochets ne sont pas autorisés à l'intérieur des fonctions simples, uniquement dans les composants de fonction et la façon dont vous l'appelez trompe Réagissez en pensant que votre composant est en réalité une fonction normale.

Peut-être que cela épargnera à quelqu'un le mal de tête, si vous utilisez react-router-dom si vous passez votre composant dans le rendu comme celui-ci (pas de la bonne manière), cela donnera Invalid Hook Call Warning
<Route path="/:cuid/:title" render={PostArticle} />

Il m'a fallu une demi-heure pour savoir où je me suis trompé

Cela peut aider quelqu'un - si vous rencontrez ce bogue après avoir utilisé react-router-dom, vérifiez comment vous avez défini vos itinéraires. par exemple, il devrait être <Route path={'/upgrade/:plan'} exact children={<Upgrade />} /> pendant que je faisais <Route path={'/upgrade/:plan'} exact children={Upgrade} />

Ceci est particulièrement gênant si vous utilisez de l' encre ou du pastel pour créer une CLI (voir https://github.com/vadimdemedes/pastel/issues/2). Je ne peux pas en faire un peerDep car je ne peux pas demander à chaque utilisateur d'installer React et je ne peux pas non plus les forcer à utiliser une certaine version/gamme de React.

Mon équipe utilise Yarn et n'obtenait l'erreur Invalid hook call que dans les tests, pas dans l'application. Le problème était que react-test-renderer se résolvait en une version inférieure à celle de react et react-dom , nous avons donc ajouté resolutions dans package.json :

"devDependencies": {
    ...
    "react": "16.12.0",
    "react-dom": "16.12.0",
    ...
},
"resolutions": {
    "react-test-renderer": "16.12.0"
}

Pour les personnes utilisant Gatsby dans un sous-répertoire, c'est une solution possible.

gatsby-node.js :

const path = require('path')
const fromRoot = name => path.resolve(__dirname + '/../node_modules/' + name)

exports.onCreateWebpackConfig = ({ actions }) => actions.setWebpackConfig({
  resolve: {
    alias: {
      'react': fromRoot('react'),
      'react-dom': fromRoot('react-dom'),
    },
  },
})

J'ai le même problème lors de l'exécution de la commande npm link ,il y a un problème

Ensuite, j'ai utilisé la solution officielle fournie par react pour résoudre ce problème

Ce problème peut également survenir lorsque vous utilisez un lien npm ou un équivalent. Dans ce cas, votre bundler peut "voir" deux Reacts - un dans le dossier de l'application et un dans le dossier de votre bibliothèque. En supposant que myapp et mylib sont des dossiers frères, une solution possible consiste à exécuter le lien npm ../myapp/node_modules/react depuis mylib. Cela devrait obliger la bibliothèque à utiliser la copie React de l'application.

Si A doit introduire B (A et B sont frères et sœurs)

  • étape 1 (en B)

    • npm link ./../A/node_modules/react

    • npm link

  • étape 2 (en A)
    npm link B

ça marche pour moi

Même avec ces réponses, je ne sais pas pourquoi j'obtiens l'erreur. J'ai ma bibliothèque de dépendances liée à mon application principale et après avoir reçu l'erreur, j'ai suivi les documents de réaction et lié la version de ma bibliothèque de dépendances de réagir à la réaction de mon application (exécutant npm link <>/webapp/node_modules/react . (même fait cela avec react- dom). Lorsque je me suis connecté pour tester si React1 et React2 étaient identiques, il a enregistré true donc je n'utilisais pas de versions en double de React, j'utilisais les mêmes versions de React et j'utilisais des composants de fonction Ainsi, même si la journalisation des tests indiquait que je n'avais pas de version en double de React, j'obtenais toujours l'erreur de crochet.

Mais essayer cette solution comme mentionné ci-dessus a corrigé ce bogue particulier :

alias: {
        react: path.resolve('./node_modules/react')
 }

Je suis donc perdu.

Je suis donc perdu.

@orpheus Rendez -vous plus d'une racine de réaction dans la même page ? c'est-à-dire avez-vous plus d'un appel ReactDOM.render sur la même page ?

Rendez-vous plus d'une seule racine de réaction dans la même page ? c'est-à-dire avez-vous plus d'un appel ReactDOM.render sur la même page ?

@timkindberg

Je ne. J'ai mon seul ReactDOM.render à la racine de mon app , et le module lib que je lie est une bibliothèque de composants et n'utilise pas de ReactDOM.render du tout.

edit : je fais quelque chose comme :

import React from 'react'
import ReactDOM from 'react-dom'
import Root from './App/Root'

ReactDOM.render(
  <Root />,
  document.getElementById('root')
)

<Root /> donne quelque chose comme

const Root = () => {
  return <Provider store={store}>
        <PermissionsProvider>
              <Suspense fallback={null}>
                <Router history={history}>
                  <Routes store={store} />
                </Router>
              </Suspense>
        </PermissionsProvider>
  </Provider>
}

PermissionsProvider est le composant React que j'importe à partir de mon module lié lib qui utilise un crochet qui provoque l'échec de l'application. Il crée l'état et le contexte et rend ses enfants.

Salut, j'utilise des électrons avec des crochets de réaction. si j'écris mon propre crochet, ça marche. Mais cela génère une erreur lorsque j'utilise des hooks d'un autre package dans node_module, comme react-use , swr .

Je dois copier le package dans mon fichier local.

Est-ce que quelqu'un rencontre ce problème ?

Exemple de projet ici :
https://github.com/Zaynex/electron-react-ts-kit/tree/hooks-error

code de base :
https://github.com/Zaynex/electron-react-ts-kit/blob/hooks-error/src/renderer/app.tsx

J'ai toujours ce problème même après avoir supprimé les copies en double de react et react-dom. J'ai créé un projet de test super simple à reproduire.

$ tree -I node_modules
.
|-- test-app
|   |-- dist
|   |   |-- index.html
|   |   `-- main.js
|   |-- package-lock.json
|   |-- package.json
|   |-- src
|   |   |-- index.html
|   |   `-- index.js
|   `-- webpack.config.js
`-- test-lib
    |-- dist
    |   `-- main.js
    |-- package-lock.json
    |-- package.json
    |-- src
    |   `-- index.js
    `-- webpack.config.js

Actuellement, j'utilise la méthode d'alias webpack, mais j'ai également essayé la méthode npm link , et aucune ne fonctionne.

Je suis également tombé sur ce problème. J'utilise ExpressJS + Pug pour rendre les vues, j'ai ensuite écrit un moteur de rendu (similaire à ReactRails) qui permet de rendre les composants côté serveur et côté client.

J'ai essayé d'extraire ceci dans un package séparé car cela devenait désordonné et je suis tombé sur ce problème.

Pour résoudre ce problème, j'ai dû ajouter sous la clé resolve :

alias: {
  react: path.resolve("./node_modules/react"),
},

Cela fonctionne maintenant comme prévu lors de l'exécution normale de webpack, mais le problème persiste avec un volume docker. Je suis trop nouveau pour docker pour m'en occuper, alors je vais y revenir plus tard.

Edit : j'ai parlé trop tôt. Cela fonctionne bien maintenant avec le rendu React, mais pas avec hydrate.

Salut, j'utilise des électrons avec des crochets de réaction. si j'écris mon propre crochet, ça marche. Mais cela génère une erreur lorsque j'utilise des hooks d'un autre package dans node_module, comme react-use , swr .

Je dois copier le package dans mon fichier local.

Est-ce que quelqu'un rencontre ce problème ?

Exemple de projet ici :
https://github.com/Zaynex/electron-react-ts-kit/tree/hooks-error

code de base :
https://github.com/Zaynex/electron-react-ts-kit/blob/hooks-error/src/renderer/app.tsx

Salut. J'ai eu le même problème. J'utilise electron-webpack qui marque tous les modules comme externes pour webpack. Avec quelques exceptions codées en dur - comme react et react-dom.
Pour moi, cela signifiait que réagir chargé à partir de mon code était différent de réagir chargé à partir de ce module.
L'ajout de ces modules à la liste blanche semble aider (je ne sais pas si cela n'a encore rien cassé d'autre :)

@huhle merci, ça marche! Peut-être devrions-nous plonger dans electron-webpack.

Je viens de réussir à le faire fonctionner moi-même. Je pense que c'est l'une des meilleures solutions en ce qui concerne les espaces de travail Lerna et Yarn, et peut-être que certaines des pièces pourraient être utilisées pour une autre solution.

Tout semble se résumer à la configuration du package.json que j'importe. J'avais besoin d'inclure ces sections:

 "peerDependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },
  "workspaces": {
    "nohoist": [
      "react", "react-dom"
    ]
  }

Après cela, j'ai dû reconstruire les projets et j'étais opérationnel. Il semble que les répertorier en tant que dépendances homologues leur permette d'être installées par votre projet consommateur. Et parce qu'ils ne sont pas répertoriés dans les dépendances, ils ne devraient pas être disponibles pour le package que vous essayez d'importer, mais pour une raison quelconque, à moins que vous ne lui disiez de ne pas lever, ils restent disponibles et une nouvelle instance de réaction fait son chemin et provoque l'erreur.

Bonne chance!

J'essaie d'utiliser react-spring pour obtenir un simple effet de fondu enchaîné. Rien ne semble fonctionner.
`import React, { useState, useEffect } from 'react';
import { animé, useTransition } de 'react-spring' ;

const TextContent = (accessoires) => {

const [items] = useState([
    { id: '0', title: 'Text1' },
    { id: '1', title: 'Text2' },
    { id: '2', title: 'Text1' }
])

const [index, setIndex] = useState(0);

const transitions = useTransition(items[index], index => index.id,
    {
        from: { opacity: 0 },
        enter: { opacity: 1 },
        leave: { opacity: 0 },
        config: { tension: 220, friction: 120 }
    }
)

useEffect(() => {
    const interval = setInterval(() => {
        setIndex((state) => (state + 1) % items.length);
    }, 4000)
    return () => clearInterval(interval);
}, []);

return (
    <div>
        {
            transitions.map(({ item, props, key }) => (
                <animated.div
                    key={key}
                    style={{ ...props, position: 'absolute' }}
                >
                    <p>{item.title}</p>
                </animated.div>
            ))
        }
    </div>
)

}

exporter le contenu textuel par défaut;`
Capture

J'ai essayé de vérifier si j'avais plusieurs instances de React. Npm ls-ing me dit que je n'ai qu'une seule version de react et react-dom, toutes deux à 16.13.1.

Salut, j'utilise des électrons avec des crochets de réaction. si j'écris mon propre crochet, ça marche. Mais cela génère une erreur lorsque j'utilise des hooks d'un autre package dans node_module, comme react-use , swr .
Je dois copier le package dans mon fichier local.
Est-ce que quelqu'un rencontre ce problème ?
Exemple de projet ici :
https://github.com/Zaynex/electron-react-ts-kit/tree/hooks-error
code de base :
https://github.com/Zaynex/electron-react-ts-kit/blob/hooks-error/src/renderer/app.tsx

Salut. J'ai eu le même problème. J'utilise electron-webpack qui marque tous les modules comme externes pour webpack. Avec quelques exceptions codées en dur - comme react et react-dom.
Pour moi, cela signifiait que réagir chargé à partir de mon code était différent de réagir chargé à partir de ce module.
L'ajout de ces modules à la liste blanche semble aider (je ne sais pas si cela n'a encore rien cassé d'autre :)

Brillant! Merci

J'essaie d'utiliser react-spring pour obtenir un simple effet de fondu enchaîné. Rien ne semble fonctionner.
`import React, { useState, useEffect } from 'react';
import { animé, useTransition } de 'react-spring' ;

const TextContent = (accessoires) => {

const [items] = useState([
    { id: '0', title: 'Text1' },
    { id: '1', title: 'Text2' },
    { id: '2', title: 'Text1' }
])

const [index, setIndex] = useState(0);

const transitions = useTransition(items[index], index => index.id,
    {
        from: { opacity: 0 },
        enter: { opacity: 1 },
        leave: { opacity: 0 },
        config: { tension: 220, friction: 120 }
    }
)

useEffect(() => {
    const interval = setInterval(() => {
        setIndex((state) => (state + 1) % items.length);
    }, 4000)
    return () => clearInterval(interval);
}, []);

return (
    <div>
        {
            transitions.map(({ item, props, key }) => (
                <animated.div
                    key={key}
                    style={{ ...props, position: 'absolute' }}
                >
                    <p>{item.title}</p>
                </animated.div>
            ))
        }
    </div>
)

}

exporter le contenu textuel par défaut;`
Capture

J'ai essayé de vérifier si j'avais plusieurs instances de React. Npm ls-ing me dit que je n'ai qu'une seule version de react et react-dom, toutes deux à 16.13.1.

Pareil ici. react et react-dom sont à 16.13.1 pour moi, et tenter d'utiliser react-spring entraîne la même erreur.

D'un autre fil de discussion sur styled-components , j'ai appris que si vous utilisez votre propre package local via un URI file: dans package.json , vous devez rm -rf node_modules/local-package-name/node_modules avant d'exécuter votre application, car apparemment, les packages locaux sont copiés sans vérifier node_modules les dépendances redondantes.

D'un autre fil de discussion sur styled-components , j'ai appris que si vous utilisez votre propre package local via un URI file: dans package.json , vous devez rm -rf node_modules/local-package-name/node_modules avant d'exécuter votre application, car apparemment, les packages locaux sont copiés sans vérifier node_modules les dépendances redondantes.

Oui, c'est le même problème pour environ une douzaine de cas d'utilisation dans ce seul fil. J'ai ajouté une cible "prestart" et "prebuild" pour faire le rm -rf (en utilisant rimraf). Un autre utilisateur de ce fil a utilisé npm-link-shared dans son pré-démarrage pour que les modules partagent la même instance de réaction. Beaucoup d'entre nous, utilisateurs de monorepo, se heurtent à cela.

Salut, j'utilise des électrons avec des crochets de réaction. si j'écris mon propre crochet, ça marche. Mais cela génère une erreur lorsque j'utilise des hooks d'un autre package dans node_module, comme react-use , swr .
Je dois copier le package dans mon fichier local.
Est-ce que quelqu'un rencontre ce problème ?
Exemple de projet ici :
https://github.com/Zaynex/electron-react-ts-kit/tree/hooks-error
code de base :
https://github.com/Zaynex/electron-react-ts-kit/blob/hooks-error/src/renderer/app.tsx

Salut. J'ai eu le même problème. J'utilise electron-webpack qui marque tous les modules comme externes pour webpack. Avec quelques exceptions codées en dur - comme react et react-dom.
Pour moi, cela signifiait que réagir chargé à partir de mon code était différent de réagir chargé à partir de ce module.
L'ajout de ces modules à la liste blanche semble aider (je ne sais pas si cela n'a encore rien cassé d'autre :)

Cela s'applique également aux personnes ayant des problèmes avec redux ou redux toolkit et electron-webpack. J'ai la config de travail suivante :

// package.json
...
"electronWebpack": {
  "whiteListedModules": ["react-redux"]
}

voir https://github.com/electron-userland/electron-webpack/issues/349

Mon problème était que j'ai écrit

import React from 'React'

Au lieu de:

import React from 'react'

Parfois, ce sont les choses stupides.

Je l'ai résolu en ajoutant ce qui suit à ma configuration webpack :

 externals: {
    react: {
      root: "React",
      commonjs2: "react",
      commonjs: "react",
      amd: "react",
    },
    "react-dom": {
      root: "ReactDOM",
      commonjs2: "react-dom",
      commonjs: "react-dom",
      amd: "react-dom",
    },
  },

J'ai d'abord pensé que c'était un problème avec le lien npm, j'ai fait tout ce qui était suggéré et je suis même passé au fil. Finalement, j'ai pensé que quelque chose d'autre se passait lors de la publication sur npm a donné la même erreur lors de l'importation dans un autre projet.

Est-ce que quelqu'un ici a résolu ce problème récemment avec un monorepo lerna? J'ai essayé quelques-unes des suggestions sans succès.

Courir dans l'erreur après avoir ajouté le code qui est commenté avec le // ci-dessous. L'ajout de CssBaseline et des informations sur le fragment de réaction provoque l'erreur. Tout va bien quand c'est commenté. Le code d'origine est simplement le code de base npx create-react-app. Complètement nouveau à cela et quelques-uns des correctifs que j'ai essayés ci-dessus n'ont pas eu d'effet.

importer React depuis 'react' ;
importer le logo depuis './logo.svg' ;
importer CssBaseline depuis '@material-ui/core/CssBaseline' ;

exporter la fonction par défaut App() {
retourner (

        //<React.Fragment>

        //<CssBaseline />

        <div className="App">
            <header className="App-header">
                <img src={logo} className="App-logo" alt="logo" />
                <p>
                    Edit <code>src/App.js</code> and save to reload.
                    </p>
                <a
                    className="App-link"
                    href="https://reactjs.org"
                    target="_blank"
                    rel="noopener noreferrer"
                >
                    Learn React
                    </a>
            </header>
        </div>

    //</React.Fragment>

);
}

Pour les tests locaux :
Dans la librairie node_modules supprimez les dossiers react et react-dom
Dans le package principal, exécutez à nouveau "yarn install" ou "npm install".

Cela empêche la deuxième copie de react d'être chargée dans le bundle principal. Évidemment, ce n'est pas une solution permanente, mais cela fonctionne pour les tests locaux.

Pour toute personne utilisant lerna, vous pouvez rencontrer ce problème lors de l'exécution de tests dans un package, où le code fait référence à des composants dans un autre package.

Le problème que nous avons rencontré dans ce cas était dû à la réaction importée dans la spécification, et également importée dans un composant de l'arborescence des composants qui utilisait Material UI's withStyles , qui est implémenté à l'aide de crochets dans Material UI.

Il semble que react gère en interne l'état dans une variable ReactCurrentDispatcher.current , et cela finit par être défini dans une instance de react, mais utilisé dans l'autre instance de react - lorsqu'il est vide, il lance le Invalid hook call ... message.

Nous utilisions déjà Craco pour remplacer la configuration du pack Web de Create React App au moment de la construction :

  webpack: {
    alias: {
      react: path.resolve(__dirname, './node_modules/react'),
    },
  },

Cependant, ce remplacement de webpack n'est utilisé qu'au moment de la construction - lors de l'exécution des tests, le code n'est pas construit, mais instancié à partir de la source - donc notre solution consistait à utiliser CracoAlias ​​dans notre craco.config.js pour spécifier le chemin de réaction lors des tests :

  plugins: [
    {
      plugin: CracoAlias,
      options: {
        source: 'options',
        baseUrl: './',
        aliases: {
          // We need to alias react to the one installed in the desktop/node_modules
          // in order to solve the error "hooks can only be called inside the body of a function component"
          // which is encountered during desktop jest unit tests,
          // described at https://github.com/facebook/react/issues/13991
          // This is caused by two different instances of react being loaded:
          // * the first at packages/desktop/node_modules (for HostSignUpDownloadComponent.spec.js)
          // * the second at packages/components/node_modules (for packages/components/Modal)
          react: './node_modules/react',
        },
      },
    },
  ],

J'ai utilisé @craco/craco comme solution, sans éjecter, en suivant l'exemple de @apieceofbart . Les étapes pour moi étaient les suivantes en utilisant npm link pour tester le module local :

  1. Installez craco sur mon application de démonstration en exécutant npm i @craco/craco --save
  2. Créez le fichier de configuration craco.config.js à la racine où package.json réside dans l'application de démonstration.
  3. Modifiez les scripts start , build et test en remplaçant react-scripts par craco dans mon application de démonstration.
// craco.config.js
const path = require('path');

module.exports = {
    webpack: {
        alias: {
            react: path.resolve(__dirname, './node_modules/react')
        }
    }
}
// package.json
{
....
"scripts": {
    "start": "craco start",
    "build": "craco build",
    "test": "craco test",
    "eject": "react-scripts eject"
  },
...
}

edit : je n'avais même pas remarqué que @jasondarwin avait eu la même idée.

J'ai passé la meilleure journée à essayer de résoudre ce problème. Publier ma solution ici au cas où cela aiderait quelqu'un.

Nous utilisons un monorepo et deux packages importaient différentes instances de react, mais ils résolvaient au même endroit dans les modules du nœud racine. Il s'avère que nous avions ces deux instances car l'une des applications utilisait son propre pack Web pour créer un ensemble. Celui-ci était correctement hissé vers le module du nœud racine, mais obtiendrait sa propre instance lors de son importation par ce package. La solution consistait à inclure réagir et réagir DOM dans les éléments externes de la configuration Webpack afin que Webpack ne crée pas une nouvelle instance de réaction pour le bundle.

externals: { react: 'react', reactDOM: 'react-dom', },

J'espère que cela aide quelqu'un!

Pour moi, il utilisait la version 4.0.0 de react-hot-loader, la mise à jour vers react-hot-loader 4.8 semble faire l'affaire

Je reçois le message Invalid hook call UNIQUEMENT lors de l'exécution de mes tests sur un crochet personnalisé que je crée pour travailler avec des fenêtres modales.

Pour illustrer le comportement, j'ai créé un exemple dans ce qui suit :
(https://github.com/BradCandell/invalid-hook-example)

  • Une seule version de react et react-dom

Ai-je raté quelque chose de terriblement évident? Quand j'ai enfreint la règle dans le passé, le npm start échouerait. Mais cela ne fait qu'échouer dans mes tests.

J'apprécie l'aide !
- Brad

Je l'ai résolu en ajoutant ce qui suit à ma configuration webpack :

 externals: {
    react: {
      root: "React",
      commonjs2: "react",
      commonjs: "react",
      amd: "react",
    },
    "react-dom": {
      root: "ReactDOM",
      commonjs2: "react-dom",
      commonjs: "react-dom",
      amd: "react-dom",
    },
  },

J'ai d'abord pensé que c'était un problème avec le lien npm, j'ai fait tout ce qui était suggéré et je suis même passé au fil. Finalement, j'ai pensé que quelque chose d'autre se passait lors de la publication sur npm a donné la même erreur lors de l'importation dans un autre projet.

Cela l'a réglé pour moi. J'importais react-toastify et recevais l'appel de crochet invalide. J'ai parcouru chaque élément dans l'erreur de la console :

  1. Vous pouvez avoir des versions incompatibles de React et React DOM.

    1. Vous pourriez enfreindre les règles des crochets.

    2. Vous pouvez avoir plusieurs copies de React dans la même application.

A fini par être le 3e numéro. J'ai suivi ceci :
https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate -react

Aucune des solutions ci-dessus n'a fonctionné pour moi, jusqu'à ce que je réalise que je regroupais une autre copie de React avec la bibliothèque que j'importais.
J'avais transpilé et regroupé le code source de ma bibliothèque, donc la vérification des différentes versions de React répertoriées dans la documentation renvoyait true au lieu de false .
Marquer react comme une dépendance externe et le laisser en dehors du paquet de ma bibliothèque a fait l'affaire.

Mon cas n'était pas un monorepo, mais une situation quelque peu similaire. Nous développons un nouveau cadre d'interface utilisateur, et au lieu d'utiliser le lien npm ou lerna, nous utilisons simplement des alias webpack pour exiger les fichiers sur un dossier frère. Cela fonctionne bien, mais vous rencontrerez ce problème. Heureusement, la solution de @apieceofbart a résolu le problème pour nous.

Ligne 130:21 : React Hook "useStyles" est appelé dans la fonction "pharmacyDashboard" qui n'est ni un composant de la fonction React ni une fonction React Hook personnalisée react-hooks/rules-of-hooks
Ligne 133:45 : React Hook "React.useState" est appelé dans la fonction "pharmacyDashboard" qui n'est ni un composant de fonction React ni une fonction React Hook personnalisée react-hooks/rules-of-hooks

c'est l'erreur ..... quelqu'un peut-il m'aider à résoudre ce problème

@vyshnaviryali tu ferais mieux d'appeler ta fonction usePharmacyDashboard

./src/components/HomeFiles/AppFooter.js
Ligne 1 : 1 : la définition de la règle « matériel-ui/no-hardcode-labels » n'a pas été trouvée. material-ui/no-hardcode-labels »
quelqu'un peut-il m'aider à résoudre ce problème

Pour tous ceux qui rencontrent ce problème avec npm link parce que vous devez ajouter des fonctionnalités à vos composants mais que vous ne voulez pas npm publish avant de tester, je suis surpris que personne n'ait suggéré d'utiliser yalc (https://www.npmjs.com/package/yalc)

Pour tous ceux qui rencontrent ce problème avec npm link parce que vous devez ajouter des fonctionnalités à vos composants mais que vous ne voulez pas npm publish avant de tester, je suis surpris que personne n'ait suggéré d'utiliser yalc (https://www.npmjs.com/package/yalc)

En fait, je l'ai fait l'année dernière : https://github.com/facebook/react/issues/13991#issuecomment -535150839

Nous l'utilisons depuis presque un an maintenant sans aucun problème.

Un autre ici utilisant lerna; pour résoudre ce problème, j'ai déplacé les dépendances react et react-dom vers ma racine package.json .

J'ai eu le même problème et je l'ai résolu en ajoutant:

 alias: {
        react: path.resolve('./node_modules/react')
      }

à la propriété resolve dans la configuration webpack de mon application principale.

C'était évidemment mon erreur d'utiliser deux copies de React mais je suis d'accord que ce serait génial si le message d'erreur était meilleur. Je pense que c'est peut-être similaire à : #2402

Pour ceux qui utilisent la méthode ci-dessus mais qui obtiennent toujours les erreurs lors de l'exécution de jest, ajoutez-les à moduleNameMapper dans la configuration de jest (omettez react-dom si ce n'est pas nécessaire):

moduleNameMapper: {

...

  "^react$": "<rootDir>/node_modules/react",
  "^react-dom$": "<rootDir>/node_modules/react-dom",

...

}

Je suis à perte. Je reçois ceci, mais mon application n'utilise aucun crochet et il n'y a pas de doublons de réaction ou de réaction-dom. J'utilise next.js. Cela pourrait-il avoir quelque chose à voir avec cela?

npm ls react
npm ls react-dom

@maapteh était-ce pour moi ? J'ai exécuté ces commandes et je n'ai trouvé aucun doublon. Les deux bibliothèques sont à la version 16.13.1

@dancancro J'utilise également Next.js et je ne parviens pas à résoudre ce problème.

npm ls react et npm ls react-dom ne renvoient qu'une seule entrée. Mais je ne suis pas sûr que ce soit correct. Je rencontre cette erreur lors de la liaison à un package local pour le développement. npm ls ne renvoie qu'une seule entrée même si je ne lie pas la réaction dans la dépendance au référentiel principal. Mais même lorsque le lien réagit correctement, j'obtiens toujours l'erreur.

@justincy Je n'ai aucun lien de package dans mon projet. Je parie que c'est lié à Next.js. Le problème disparaît si je mets le composant principal à l'intérieur d'un typeof document !== 'undefined' , sapant ainsi l'objectif de Next.js

J'ai réussi à résoudre mon problème en supprimant react et react-dom de node_modules dans la dépendance. Ce n'est pas l'idéal, mais au moins je peux continuer à travailler.

@dancancro Je suis sceptique quant au fait que votre problème soit causé par Next.js. Si c'était le cas, beaucoup d'autres personnes auraient le problème. Je ne le rencontre qu'à cause des packages liés. Je ne vois pas l'erreur sans packages liés.

Le problème disparaît si je supprime cinq des sept composants du composant principal. Je ne vois rien de spécial à propos de ces composants. Envelopper ces composants dans typeof document !== 'undefined' s fonctionne également.

Salut l'équipe, j'essaie de mettre à niveau la version React de 16.2.0 à 16.13.1, j'ai également fait la même chose pour react-dom.
Maintenant, j'ai un composant wrapper qui est appelé à "/test"

class TestWrapper extends React.Component { render() { return ( <React.Fragment> <TestComponent /> </React.Fragment> ) } }

dans le wrapper de test, j'ai importé un composant fonctionnel avec un crochet
function TestComponent(props) { useEffect(() => { console.log("TEST COMPONENT"); }); return ( <div> Hello world! </div> ) }

Mais lorsque la page rend le crochet UseEffect ne fonctionne pas et qu'une erreur se produit, c'est-à-dire un avertissement d'appel de crochet non valide
PS. :

  1. J'ai vérifié que je n'ai qu'une seule copie de react et que react-dom est installé
  2. La version de React et React-dom est 16.13.1

C'est ce que j'ai
Je viens de...
@ @
ReactError
J'utilise nextJS donc il n'a pas besoin d'importer React. Et je l'ai essayé - n'aide pas.

Toutes les autres pages et fonctions fonctionnent parfaitement

@Brotipok quelle version de next.js ? (Voyant des problèmes similaires, mais uniquement lors du passage à 9.5 à partir de 9.4.X)

Salut!

J'ai la même erreur, un seul paquet pour réagir et réagir dom quand je fais npm ls.

Réagir version : 16.13.1
Version React-dom : 16.13.1

J'utilise dactylographié et j'ai initialisé le projet avec create-react-app my-app --template typescript.

Le composant fonctionnel ne fonctionne que si je n'utilise pas de crochets à l'intérieur.

Package.json

{
"name": "blablamovie",
"version": "0.1.0",
"privé": vrai,
"dépendances": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"@types/jest": "^24.9.1",
"@types/nœud": "^12.12.53",
"@types/réagir": "^16.9.43",
"@types/react-dom": "^16.9.8",
"@types/react-router-dom": "^5.1.5",
"react-icons": "^3.10.0",
"réagir-scripts": "3.4.1",
"typescript": "^3.7.5",
"webpack-bundle-analyzer": "^3.8.0"
},
"scripts": {
"start": "react-scripts start",
"build": "construction de scripts réactifs",
"test": "test des scripts réactifs",
"eject": "éjecter les scripts de réaction",
"analyze": "source-map-explorer 'build/static/js/*.js'"
},
"eslintConfig": {
"extend": "réagir-app"
},
"liste des navigateurs": {
"production": [
">0,2 %",
"pas mort",
"pas op_mini tout"
],
"développement": [
"1 dernière version chromée",
"dernière version de firefox",
"dernière version safari"
]
}
}
C'est un projet important et ça me rend un peu fou.
Si quelqu'un peut aider, ce serait super.
Merci.

@Brotipok quelle version de next.js ? (Voyant des problèmes similaires, mais uniquement lors du passage à 9.5 à partir de 9.4.X)

Voici les dépendances
"dépendances": {
"suivant": "9.4.4",
"images-suivantes": "^1.4.0",
"node-sass": "^4.14.1",
"réagir": "16.13.1",
"react-document-meta": "^3.0.0-beta.2",
"react-dom": "16.13.1",
"react-horizontal-timeline": "^1.5.3",
"react-meta-tags": "^0.7.4",
"react-onclickoutside": "^6.9.0"
},
"devDependencies": {
"@types/nœud": "^14.0.23",
"@types/réagir": "^16.9.43",
"typescript": "^3.9.7"
}

Je rencontre le même problème lors de l'importation de composants material-ui/core/Dialog , j'ai défini mon package.json pour utiliser réagir 16.8.0 spécifiquement pour react et react-dom Importations

J'ai exécuté npm ls react et npm ls react-dom avec une seule importation. J'ai également essayé le test décrit dans la page d'erreur :

// Add this in node_modules/react-dom/index.js
window.React1 = require('react');

// Add this in your component file
require('react-dom');
window.React2 = require('react');
console.log(window.React1 === window.React2);

Qui renvoie false , mais comment puis-je retrouver la version de réaction "différente" qui est importée par une dépendance ?, cela ne semble se produire que lorsque j'importe le composant Material UI Dialog , cela se produit dès que vous appuyez sur un bouton qui le déclenche pour le rendu. Je peux utiliser d'autres composants tels que List et ListItems , etc.

J'ai essayé de forcer les résolutions et cela n'a pas résolu le problème non plus.

Je n'utilise pas de pack Web (vraiment un petit projet), donc la construction se produit avec react-scripts build si cela fait une différence.

Réécrire : je remplacerai simplement ma question par une référence de solution (et peut-être une demande pour encore plus de clarté dans la documentation, pour nous les nuls ? :) )

Contexte:
J'essayais de compiler en webpack un composant fonctionnel avec des crochets dans un actif où ce composant pouvait être appelé à partir de vanilla JS dans le navigateur.

Par exemple,

function Example() {
    const [count, setCount] = React.useState(0);

    return <button onClick={() => setCount(count + 1)}>
        You clicked {count} times
    </button>;
}
export default Example;

... que je voulais exporter en tant que module en soi, et après avoir chargé cet actif, utilisez-le directement à partir de HTML, similaire à :

<script defer>
            ReactDOM.render(
                ExportedCompiledExample.default(props),
                document.getElementById("my_element")
            );
</script>

Je l'ai fait fonctionner il y a longtemps _tant que le composant ne contenait pas de crochets_. Mais lors de l'utilisation de crochets, je n'arrêtais pas de tomber sur ce message d'erreur redouté.

La solution simple et renversante
J'ai suivi _beaucoup_ de harengs rouges plus compliqués (plusieurs versions/instances de react/reactDOM, importations npm et dépendances secondaires cachées, react-hot-loader, configuration de webpack, externes, différentes conventions de bundle/module/bibliothèque, structure post-compilation .. .) avant d'essayer ceci, qui a fonctionné :

export default () => <Example />;

(ou export default props => <Example {...props} /> cas échéant).

En rétrospective 20/20 ça a du sens, je suppose.

Mais juste pour identifier la source de confusion au cas où quelqu'un d'autre en aurait besoin : les documents sur les règles de crochets disent _Appelez-les au niveau supérieur dans le corps d'un composant de fonction_. Ce que je pensais avoir fait, puisque j'ai en fait collé l'exemple directement dans ma structure.

Mon interprétation est que cela , à partir des exemples...

function Example() {
  // Declare a new state variable, which we'll call "count"
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

... n'est PAS un composant fonctionnel en soi ? Cela le devient dans le bon contexte d'appel (donc, pas Example() mais <Example /> ).

Je suppose que je l'ai peut-être manqué ailleurs dans la documentation, mais dans le cas contraire : cela m'aurait fait gagner beaucoup de temps si un peu de contexte d'utilisation (ou juste une configuration de module ES) était inclus/mentionné/lié à. :) D'autant plus que la version directe export default Example fonctionne sans crochets.

Merci pour une solution de travail @apieceofbart ! Mon problème était lié au lien npm.

Voici comment je l'ai fait fonctionner avec Create React App, où la configuration Webpack est masquée par conception. C'est peut-être aussi ta solution @florianzemma ?

  1. npm install -D react-app-rewired
  2. Créez un fichier appelé config-overrides.js dans la racine de votre projet.
// config-overrides.js
module.exports = function override(config, env) {
  const path = require('path');

  return {
    ...config,
    resolve: {
      ...config.resolve,
      alias: {
        ...config.resolve.alias,
        react: path.resolve('./node_modules/react')
      }
    }
  };
}
  1. Remplacez les react-scripts ... -commands pertinentes dans package.json par react-app-rewired ... .

j'espère que ça aide

J'ai eu cette erreur parce que j'ai chargé les bundles 2 fois.
Dans mon cas, cela s'est produit parce que le modèle nunjucks où les balises de script ont été rendues a été utilisé 2 fois - dans la mise en page elle-même et dans le modèle général pour le contenu de la balise head,

Solution de contournement de fil

J'utilise Yarn et j'ai résolu ce problème en forçant la résolution dans mon package.json :

  "resolutions": {
    "**/react": "16.7.0-alpha.2",
    "**/react-dom": "16.7.0-alpha.2"
  },

Outre l'ajout de la résolution dans l'application parente (bibliothèque consommatrice), j'ai mis à jour les dépendances de la bibliothèque avec les commandes suivantes :

  1. yarn add link:/path/to/parent-app/node_modules/react
  2. yarn add link:/path/to/parent-app/node_modules/react-dom

Après cela, j'ai reconnecté la bibliothèque à l'application parente avec yarn add link:/path/to/library

salut
Je rencontre le même problème avec les espaces de travail de fil.
J'ai une mise en page comme celle-ci:

espace de travail/
├── bibliothèque/
├── application1/
├── app2/

app1 et app2 ont des dépendances directes pour réagir v16.9.0, réagir-dom v16.9.0 et 'library'.
'library' a une dépendance de pairs pour réagir v16.9.0 mais aussi une dépendance de dev sur storybook.
Le problème semble provenir du livre de contes qui dépend de la réaction v16.13.1.
Cependant, lorsque j'exécute l'installation de fil, je me retrouve avec réagir 16.13.1 dans mes node_modules de niveau supérieur et réagir 16.9.0 dans les node_modules locaux de app1 et app2.

Lorsque j'exécute app1 (créé avec CRA), il utilise sa réaction locale v16.9.0, mais les composants de la 'bibliothèque' utilisent React v16.13.1

Cela me semble être un problème avec la logique de levage de fil, la définition de webpack de create-react-apps ou les deux ?
Quelqu'un a-t-il une idée d'une solution de contournement pour ce scénario?

salut
Je rencontre le même problème avec les espaces de travail de fil.
J'ai une mise en page comme celle-ci:

espace de travail/
├── bibliothèque/
├── application1/
├── app2/

app1 et app2 ont des dépendances directes pour réagir v16.9.0, réagir-dom v16.9.0 et 'library'.
'library' a une dépendance de pairs pour réagir v16.9.0 mais aussi une dépendance de dev sur storybook.
Le problème semble provenir du livre de contes qui dépend de la réaction v16.13.1.
Cependant, lorsque j'exécute l'installation de fil, je me retrouve avec réagir 16.13.1 dans mes node_modules de niveau supérieur et réagir 16.9.0 dans les node_modules locaux de app1 et app2.

Lorsque j'exécute app1 (créé avec CRA), il utilise sa réaction locale v16.9.0, mais les composants de la 'bibliothèque' utilisent React v16.13.1

Cela me semble être un problème avec la logique de levage de fil, la définition de webpack de create-react-apps ou les deux ?
Quelqu'un a-t-il une idée d'une solution de contournement pour ce scénario?

La seule solution que j'ai trouvée pour cela était de yarn run eject l'application CRA et de changer l'ordre de la section resolve de :

```javascript
modules : ['node_modules', paths.appNodeModules].concat(
modules.additionalModulePaths || []
),
````

pour
```javascript
modules : [paths.appNodeModules, 'node_modules'].concat(
modules.additionalModulePaths || []
),
````

Il me semble étrange que 'appNodeModules' ne soit pas la priorité la plus élevée - l'application en question devrait-elle être reportée lorsqu'il s'agit de résoudre les dépendances?

J'ai rencontré le problème des "crochets" dans un contexte impliquant Webpack et Electron. Mon projet dépend d'un module A qui est lui-même fourni par Webpack (et que j'ai moi-même créé). J'ai externalisé React de A (en le déclarant être un module commonjs2). Cela exclut les fichiers React du bundle de bibliothèques.

Mon programme principal, exécuté dans le processus Electron Renderer, utilise également React. J'ai demandé à Webpack d'inclure React dans le bundle (pas de configuration spéciale).

Cependant, cela a produit le problème des "crochets" en raison de deux instances de React dans l'environnement d'exécution.

Ceci est causé par ces faits :

  • le module A "nécessite" React et cela est résolu par le système de modules d'Electron. Electron prend donc React de node_modules ;
  • le programme principal s'appuie sur le runtime Webpack pour "charger" React à partir du bundle lui-même.
  • Electron et le runtime Webpack ont ​​leur propre cache de module...

Ma solution consistait également à externaliser React du programme principal. De cette façon, le programme principal et le module A obtiennent leur React d'Electron - une seule instance en mémoire.

J'ai essayé un certain nombre d'alias, mais cela ne résout pas le problème car un alias indique uniquement à Webpack où trouver le code du module. Cela ne fait rien par rapport au problème des caches de modules multiples !

Si vous rencontrez ce problème avec un module que vous ne pouvez pas contrôler, découvrez si et comment React est externalisé. Si ce n'est pas externalisé, je pense que vous ne pouvez pas résoudre ce problème dans le contexte d'Electron. S'il est simplement externalisé en tant que global, placez React dans votre fichier .html et faites en sorte que votre programme principal en dépende également.

Finalement...

//webpack.config.js

module.exports = {
  ...
  externals: {
      react: 'react',
  },
}

Vue3 a le même problème

J'ai résolu ce problème en mettant react et react-dom comme peerDependencies dans mon package.json de ma bibliothèque externe, qui utilise React.

  "peerDependencies": {
    "react": "^16.13.1",
    "react-dom": "^16.13.1"
  },

Je suppose que je l'ai peut-être manqué ailleurs dans la documentation, mais dans le cas contraire : cela m'aurait fait gagner beaucoup de temps si un peu de contexte d'utilisation (ou juste une configuration de module ES) était inclus/mentionné/lié à. :) D'autant plus que la version directe export default Example fonctionne sans crochets.

Salut @espen42 ,
J'espérais vraiment que votre solution nous aiderait. Nous avons littéralement tout essayé, comme vous l'avez mentionné.

Malheureusement, votre solution ne semble pas aider non plus. Je me demande peut-être que j'ai raté quelque chose?

Ainsi, dans un package (je l'appellerai @bla/bla), nous avons le index.js qui a un composant avec des crochets, comme

function Bla = ({...props]) => {
const [bla, setBla] = useState(false);
return bla ? <div {...props} /> : 'no luck';
}

Nous compilons le package en utilisant npx babel .

Nous lions ce package avec npm link puis l'incluons dans le projet comme npm link @bla/bla .
Le package et le projet utilisent la même version de React et de react-dom.

Dans le projet, nous incluons le package comme ceci :

import Bla from `@bla/bla`

const RenderBla = ({...props}) => <Bla {...props} />

export default RenderBla

Malheureusement, l'erreur persiste toujours.
Invalid hook call. Hooks can only be called inside of the body of a function component.

Que pouvons-nous manquer ?

"externals": {
  "react": "react",
  "react-dom": "react-dom"
}

Celui-ci a résolu le problème pour moi, merci beaucoup mec ❤️

Erreur de personnalisation de champ lors de l'accès via un lien externe (Sharepoint Online)

Une extension de personnalisation de champ spfx avec quelques composants d'interface utilisateur de fabric, lorsqu'elle est accessible via un lien, obtenant l'une de ces erreurs en fonction de la version de fabricUI :
https://reactjs.org/docs/error-decoder.html/?invariant=321 ,
https://reactjs.org/docs/error-decoder.html/?invariant=290&args []=A.%20General

lorsque la page est rafraîchie, tout fonctionne correctement.
Je n'ai utilisé aucun crochet React dans le code, seulement des composants React.
Je n'ai pas utilisé de références non plus.

Je pense que cela pourrait être dû à la cause Fabric ui lorsque tous les composants fabric ui sont supprimés, aucune erreur ne se produit.

J'ai essayé différentes versions de fabic ui, 6.189.2, 6.214.0 et 7.114.1 et également essayé de remplacer toutes les références fabric-ui par fluent ui, le problème persiste toujours

vérifié les versions de réaction, voici la sortie
npm ls réagir
+-- @microsoft/ [email protected]
| +-- @microsoft/office-ui-fabric- react [email protected]
| | -- [email protected] deduped | +-- @microsoft/[email protected] | | -- [email protected] dédupliqué
| +-- @microsoft/ [email protected]
| | -- [email protected] deduped | -- [email protected] dédupliqué
`-- [email protected]

Salut tout le monde,
Je suis également tombé sur cette erreur ennuyeuse. Dans mon cas, il s'agissait également d'une mauvaise configuration de ma construction de webpack à la fin. Mais aucune des choses suggérées dans ce numéro n'a fonctionné pour moi. Donc je veux aussi partager mon expérience.

Ma page comprend plusieurs points d'entrée et le SplitChunkPlugin peut créer des morceaux d'exécution. Parce que nous utilisons le gem rails-webpacker, il a été configuré par défaut pour créer un runtime pour chaque morceau. Mais webpack fait quelque chose de similaire par défaut, il inclut le runtime à l'intérieur des morceaux.

Bien sûr, la documentation met en garde contre ce cas, mais vous devez le trouver. Définir le optimization.runtimeChunk sur single créera un runtime séparé. Cela empêchera votre build d'instancier plusieurs copies de react, lors de l'utilisation de react à partir de plusieurs points d'entrée.

Voir https://webpack.js.org/configuration/optimization/#optimizationruntimechunk

Salut tout le monde,
J'ai le problème que je veux utiliser une bibliothèque externe qui vient d'un CDN et est incluse avec une balise <script> , donc je ne peux pas faire grand-chose avec le code lui-même. La bibliothèque utilise react et hooks, donc j'obtiens le
3. You might have more than one copy of React in the same app erreur.
Malheureusement, il n'y a pas de package NPM pour la bibliothèque : https://github.com/Anyline/anyline-ocr-anylinejs-module
J'utilise CRA et le projet n'est pas éjecté.

Création d'un petit exemple Sandbox .

Il génère la même erreur car l'autre package utilise également des hooks mais avec son propre React. J'ai dû publier mon package sur NPM, puis l'importer directement depuis NPM. Ce

Je suis tombé sur ce problème récemment et je me demande pourquoi.
Je l'ai résolu en le téléchargeant sur GitLab et en l'installant par adresse.
Quelle est la différence entre le package et le package local ?

J'ai trouvé que j'obtiens le "Hook call invalide". lorsque je charge dynamiquement le composant qui appelle le hook.

Bac à sable de code

Le test qui charge "App" réussit statiquement. Les deux tests qui le chargent dynamiquement (un utilisant require , un utilisant import comme fonction) donnent tous deux l'erreur.

Pourquoi je m'en soucie même: j'essaie d'écrire des tests dans lesquels j'utilise jest.doMock pour simuler certaines choses, puis je charge dynamiquement le module que je veux tester, conformément à la documentation . J'utilise doMock au lieu de Mock car j'ai besoin de pouvoir me moquer des choses différemment dans différentes fonctions. Vous remarquerez que l'erreur se produit sans aucune moquerie impliquée, cependant.

Il génère la même erreur car l'autre package utilise également des hooks mais avec son propre React. J'ai dû publier mon package sur NPM, puis l'importer directement depuis NPM. Ce

Je suis tombé sur ce problème récemment et je me demande pourquoi.
Je l'ai résolu en le téléchargeant sur GitLab et en l'installant par adresse.
Quelle est la différence entre le package et le package local ?

@catsheue était React1 === React2 true pour toi ?
je n'ai pas publié le mien dans npm mais je voulais savoir si c'était la cause

le mien semble être React1 === React2 = true et je n'ai pas trouvé de solution pour expliquer pourquoi cela se produit lorsque j'importe ma bibliothèque de réaction dans un projet

Avait ce même problème en utilisant yarn link pour tester une bibliothèque locale. Mon erreur répertoriait react et react-dom comme dépendances de développement non homologues.

Donc j'aurais dû faire yarn add --peer react react-dom . Enfin, parce que j'ai déjà commis l'erreur de valider React en tant que dépendance de développement, j'ai dû purger node_modules de ma bibliothèque. rm -rf node_modules; yarn a résolu le problème pour moi.

J'ai moi aussi été confronté à ce problème. Dans mon cas, cela a été causé par un doublon de React de Storybook (v6.0.28). Je crois que vous pouvez trouver plus d'informations ici .

J'ai désinstallé les dépendances de Storybook, supprimé node_modules et exécuté à nouveau yarn install . Cela a fonctionné pour moi. J'espère que cela aidera quelqu'un à éviter les larmes et les heures perdues à ce sujet.

Cette solution de contournement fonctionne également pour moi. J'utilise Firebase Functions et j'ai un dossier node_modules à la fois dans la racine de mon projet et dans le répertoire /functions/ . Si je supprime /functions/node_modules , mon application fonctionne correctement. C'est une solution de contournement, mais c'est assez ennuyeux. Quelqu'un a-t-il trouvé une solution de contournement permettant aux deux dossiers node_modules d'exister en même temps ?

Pour la postérité et tous ceux qui pourraient être confrontés à ce problème lors de l'utilisation de mdbootstrap dans une application créée avec create-react-app .

J'ai vu cette erreur lors de l'ajout de divers composants mdbootstrap tels que des boutons et des images de carte. La sortie de la console ajoutée à index.js pour le dépannage conformément à l'article de support de React a renvoyé true lors de la comparaison des versions. J'ai donc dû essayer autre chose.

Le correctif consistait à exécuter un npm dedupe

npm ls react

+-- [email protected]
| `-- [email protected]
`-- [email protected]

npm dedupe

npm ls react

+-- [email protected]
| `-- [email protected]  deduped
`-- [email protected]

Après cela, tous les composants ont fonctionné très bien. Jours heureux.

J'ai trouvé que j'obtiens le "Hook call invalide". lorsque je charge dynamiquement le composant qui appelle le hook.

Bac à sable de code

Le test qui charge "App" réussit statiquement. Les deux tests qui le chargent dynamiquement (un utilisant require , un utilisant import comme fonction) donnent tous deux l'erreur.

Pourquoi je m'en soucie même: j'essaie d'écrire des tests dans lesquels j'utilise jest.doMock pour simuler certaines choses, puis je charge dynamiquement le module que je veux tester, conformément à la documentation . J'utilise doMock au lieu de Mock car j'ai besoin de pouvoir me moquer des choses différemment dans différentes fonctions. Vous remarquerez que l'erreur se produit sans aucune moquerie impliquée, cependant.

@ miket01 Exactement ce que j'essaie de faire (mais sans moquerie). Avez-vous trouvé une solution?

Rencontré ce faire:

function HeadedSection (props) {
   if (!ReactDOMServer.renderToStaticMarkup(props.children))
        return null;

    const [hidden, set_hidden] = useState(props.hidden);

Fixé en appelant d'abord useState :

function HeadedSection (props) {
    const [hidden, set_hidden] = useState(props.hidden);

    if (!ReactDOMServer.renderToStaticMarkup(props.children))
        return null;

Je reçois toujours cette erreur après l'avoir mise de côté pendant plusieurs mois.

J'utilise des crochets zéro dans mon programme. Il y a exactement une copie de react et une copie de react-dom et ce sont la même version. Il n'y a pas de liens.

Cela avait en partie fonctionné avant que j'essaye récemment de mettre à jour quelques packages pour résoudre des problèmes de sécurité. J'utilise next.js et le correctif consistait à exclure certains sous-composants du composant de niveau supérieur en les enveloppant dans {typeof window !== 'undefined' , mais cela ne fonctionne plus non plus.

[18:50:42] (master) questions
// ♥ npm ls react
[email protected] /Users/Dan/work/b/questions
└── [email protected]

[22:46:34] (master) questions
// ♥ npm ls react-dom
[email protected] /Users/Dan/work/b/questions
└── [email protected]

[22:46:55] (master) questions
// ♥ npm dedupe
removed 55 packages, moved 46 packages and audited 1712 packages in 65.449s

33 packages are looking for funding
  run `npm fund` for details

found 26 vulnerabilities (15 low, 3 moderate, 8 high)
  run `npm audit fix` to fix them, or `npm audit` for details

L'erreur est générée parce que ReactCurrentDispatcher.current === null mais je ne trouve nulle part dans le /node_modules/react/cjs/react.development.js où ceci est défini sur quelque chose.

Quelqu'un peut-il me dire où ReactCurrentDispatcher.current devrait obtenir une valeur ?
https://github.com/facebook/react/search?p=2&q=%22ReactCurrentDispatcher.current+%3D%22&type=code

Cela ressemble à un candidat, mais ce code n'est pas contenu dans mon react-development.js . Devrait-ce être?

    const prevPartialRenderer = currentPartialRenderer;
    setCurrentPartialRenderer(this);
    const prevDispatcher = ReactCurrentDispatcher.current;
    ReactCurrentDispatcher.current = Dispatcher;

https://github.com/facebook/react/blob/702fad4b1b48ac8f626ed3f35e8f86f5ea728084/packages/react-dom/src/server/ReactPartialRenderer.js#L859

J'obtiens cette erreur avec le rendu côté serveur par next.js et ce code se trouve dans la source de réaction sous react-dom/server . Comment puis-je déterminer si /node_modules/react/cjs/react-development.js est correct ?

MISE À JOUR: C'était le problème. J'avais édité webpack.config.externals dans mon fichier next.config.js
https://github.com/vercel/next.js/issues/17592#issuecomment -712443172

Mon application génère une erreur massive (appel de crochet invalide) chaque fois que j'essaie d'y intégrer une interface utilisateur matérielle. Je suis complètement nouveau sur React donc j'ai besoin d'aide.

Cette page vous a été utile?
0 / 5 - 0 notes