Hooks reagieren Fehler: Hooks können nur innerhalb des Körpers einer Funktionskomponente aufgerufen werden

78

Ich erhalte diesen Fehler, wenn ich den useStateHaken benutze . Ich habe dies in seiner Grundform und schaue in den Reaktionsdokumenten nach einer Referenz, erhalte aber immer noch diesen Fehler. Ich bin bereit für den Moment mit der Gesichtspalme ...

export function Header() {
  const [count, setCount] = useState(0)
  return <span>header</span>
}
loganfromlogan
quelle
2
Funktioniert bei mir ... keine Fehler ... hast du auf 16.7 aktualisiert?
SakoBu
Ja hab ich. Ich denke, vielleicht hat es etwas anderes mit meinem Setup zu tun, aber ich habe keine Ahnung, was. Wenn ich denselben Hook oben in der Funktions-App-Komponente verwende, wird der gleiche Fehler angezeigt.
Loganfromlogan
Hmmm ... alles was ich getan habe war npx create-react-app newhook und dann Garn hinzufügen react @ next und react-dom @ next und es hat gut funktioniert ...
SakoBu
8
Nur eine Information für alle, die hier landen. Sie müssen sowohl React als auch ReactDOM auf @next aktualisieren, damit Hooks funktionieren. Wenn Sie dies nicht tun, wird durch Reagieren der obige Fehler ausgelöst. Ich weiß, weil ich gerade dieses Problem hatte und das meine Lösung war.
Tony

Antworten:

40

Aktualisiert: 2018-Dez

Neue Version von react-hot-loaderist ab sofort erhältlich, Link . Hooks funktioniert jetzt sofort. Vielen Dank an den Autor, theKashey.

Schauen Sie sich diese Boilerplate https://github.com/ReeganExE/react-hooks-boilerplate an

  • Haken reagieren
  • Hot Loader reagieren
  • Webpack, Babel, ESLint Airbnb

Vorherige Antwort:

Stellen Sie zunächst sicher, dass Sie react@nextund installiert haben react-dom@next.

Überprüfen Sie dann, ob Sie verwenden react-hot-loaderoder nicht.

In meinem Fall könnte das Deaktivieren von Hot Loader & HMR funktionieren.

Siehe https://github.com/gaearon/react-hot-loader/issues/1088 .

Zitiert:

Ja. RHL ist zu 100% nicht mit Haken kompatibel. Dafür gibt es nur wenige Gründe:

SFC werden in Klassenkomponenten konvertiert. Es gibt einen Grund, Update auf HMR erzwingen zu können, solange es auf SFC keine "Update" -Methode gibt. Ich suche nach einer anderen Möglichkeit, das Update zu erzwingen (so. Also tötet RHL SFC.

"hotReplacementRender". RHL versucht, Reacts Arbeit zu erledigen und die alte und die neue App zu rendern, um sie zusammenzuführen. Das ist jetzt offensichtlich kaputt.

Ich werde eine PR entwerfen, um beide Probleme zu entschärfen. Es wird funktionieren, aber nicht heute.

Es gibt eine bessere Lösung, die funktionieren würde - Cold API

Sie können RHL für jeden benutzerdefinierten Typ deaktivieren.

import { cold } from 'react-hot-loader';

cold(MyComponent);

Suchen Sie nach "useState/useEffect"Quellcode innerhalb der Komponente und "kalt".

Aktualisiert:

Gemäß der Aktualisierung des React-Hot-Loader-Betreuers können Sie versuchen react-hot-loader@next, die Konfiguration wie folgt festzulegen:

import { setConfig } from 'react-hot-loader';

setConfig({
  // set this flag to support SFC if patch is not landed
  pureSFC: true
});

Vielen Dank an @loganfromlogan für das Update.

Ninh Pham
quelle
Vielen Dank für den Hinweis :). Ich verwende React-Hot-Loader, daher ist es sinnvoll, dass es nicht funktioniert. Ich bin mir jedoch noch nicht 100% sicher, ob noch etwas anderes los ist. Ich werde dieses Problem auf dem React-Hot-Loader verfolgen und diese Frage aktualisieren, nachdem ein Fix veröffentlicht wurde.
Loganfromlogan
Ich kann jetzt bestätigen, dass das Deaktivieren des React-Hot-Loaders diesen Fehler behoben hat.
Loganfromlogan
2
Wenn Sie Ihre Komponente zufällig als Inline-jsx-Funktionsaufruf rendern, wird der Fehler auch dann noch verursacht, wenn die Komponente umbrochen wird cold. Also {MyComponent(props)}wird nicht funktionieren, aber <MyComponent {...props} />wird.
Dimitar Nikovski
Es gibt eine Möglichkeit, dies jetzt mit dem React-Hot-Loader zum Laufen zu bringen. Lesen Sie diesen Kommentar des Betreuers von
React
32

Mein Problem war das Vergessen, das react-domModul zu aktualisieren . Siehe Ausgabe .

JLarky
quelle
3
Ich auch! Ich benutze Create-React-App und Typescript
Jonglierkatzen
1
Ich verwende React und React-Dom Version 16.8.3, habe aber immer noch das gleiche Problem
huykon225
15

Hatte das gleiche Problem. Mein Problem hing mit React Router zusammen. Ich hatte versehentlich benutzt

<Route render={ComponentUsingHooks} />

anstatt

<Route component={ComponentUsingHooks} />
peternyc
quelle
1
Dieser Kommentar hat mir auch das Leben gerettet. Ich habe 3 Stunden damit verschwendet und mein Projekt in Stücke gerissen. War ein Tippfehler im Router
Ben Gannaway
3

Ich konnte dieses Problem lösen, indem ich die primitiven Hooks von React in die Komponentendatei importierte und sie dann an meine benutzerdefinierten Hooks übergab. Aus irgendeinem Grund tritt der Fehler nur auf, wenn ich den React-Hook (wie useState) in meine benutzerdefinierte Hook-Datei importiere.

Ich importiere useState in meine Komponentendatei:

import React, {useState} from 'react'; // import useState

import {useCustomHook} from '../hooks/custom-hook'; // import custom hook

const initialState = {items: []};
export default function MyComponent(props) {
    const [state, actions] = useCustomHook(initialState, {useState});
    ...
}

Dann in meiner Hook-Datei:

// do not import useState here

export function useCustomHook(initialValue, {useState}) {
    const [state, setState] = useState(initialValue || {items: []});

    const actions = {
        add: (item) => setState(currentState => {
            const newItems = currentState.items.concat([item]);
            return {
                ...currentState,
                items: newItems,
            };
        }),
    };

    return [state, actions];
}

Diese Methode hat die Testbarkeit meiner Hooks verbessert, da ich die Bibliothek von React nicht verspotten muss, um die primitiven Hooks bereitzustellen. Stattdessen können wir einen Mock- useStateHook direkt an die Funktion des benutzerdefinierten Hooks übergeben. Ich denke, dies verbessert die Codequalität, da Ihre benutzerdefinierten Hooks jetzt keine Kopplung mit der React-Bibliothek haben, was eine natürlichere funktionale Programmierung und Prüfung ermöglicht.

Mickmister
quelle
3

Ich hatte ein Problem in einem Monorepo, in dem ein Paket docz verwendet wurde [email protected]und das endgültige Ausgabepaket zwei Reaktionsversionen hatte.

Ausgabe auf Github

Es wurde behoben, indem das Paket 😅 entfernt wurde

rista404
quelle
2

Das Problem für mich war in der Tat React-Hot-Loader .

Sie können den React-Hot-Loader für eine einzelne Komponente anstelle der gesamten App mithilfe der folgenden coldMethode deaktivieren :

import { cold } from 'react-hot-loader'

export const YourComponent = cold(() => {

  // ... hook code

  return (
    // ...
  )
})

ODER

export default cold(YourComponent)
protoEvangelion
quelle
2

Nur um die Antwort von @ rista404 näher zu erläutern, einschließlich doppelter Versionen von react(und vielleicht react-dom), wird der gleiche Fehler ausgegeben, je nachdem, wo Sie Ihre Hooks verwenden. Hier sind zwei Beispiele ...

  1. Eine externe Abhängigkeit enthält eine andere Version reactin seinem dependencies, wahrscheinlich durch einen Fehler wie reactin der Regel eine Peer - Abhängigkeit sein sollte. Wenn npmdiese Version nicht automatisch mit Ihrer lokalen Version dedupliziert wird, wird dieser Fehler möglicherweise angezeigt. Darauf bezog sich @ rista404.
  2. Sie npm linkein Paket, das reactin seinem devDependenciesoder enthält dependencies. Bei Modulen in diesem Paket werden möglicherweise Fehler angezeigt, wenn sie eine andere Version reactaus dem lokalen node_modulesVerzeichnis als aus dem übergeordneten Projekt abrufen.

Letzteres kann festgelegt werden , wenn sie mit der Bündelung webpackunter Verwendung resolve.aliaswie so ...

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

Dadurch wird sichergestellt, dass reactimmer aus dem node_modulesVerzeichnis des übergeordneten Projekts gezogen wird .

Skipjack
quelle
2

Stellen Sie für diejenigen, die auf dieses Problem stoßen, wenn Sie MobX verwenden und eine Komponente mit einem umschließen observer, sicher, dass Sie mobx-react-liteanstelle von verwenden mobx-react.

29. MAI UPDATE

Von mobx-react 6.0.0 weiter, sind Haken basierte Komponenten nun unterstützt mobx reagieren , so gibt es für keine Notwendigkeit mobx-react-liteNutzung mehr (wenn das Ihr Problem war).

Marcelo Cardoso
quelle
1

fand diese Problemumgehung für react-hot-loader während der PR, um das Problem zu beheben, eingehend ist.

Schließen Sie die Funktion, die Hooks aufruft, in a ein React.memound verhindern Sie ein erneutes Laden im laufenden Betrieb, wenn sie unverändert bleibt.

const MyFunc = React.memo(({props}) => {...

Gutschrift für die Lösung: https://github.com/gatsbyjs/gatsby/issues/9489

Chance Eakin
quelle
1

Mein Problem war das folgende:

Ich habe getan: ReactDOM.render(Example(), app);

Während ich hätte tun sollen: ReactDOM.render(<Example />, app);

nwparker
quelle
1
Dies war auch mein Problem und ich bin froh, es unter den Antworten hier zu finden.
Seth Bro
Dies war auch mein Problem und ich bin froh, es unter den Antworten hier zu finden. Ich vermutete, dass es eine subtile Dummheit meiner eigenen Sache sein würde, aber da es eindeutig einige echte Probleme mit der Verdoppelung von Modulen in Bündlern gibt , ging ich in ein 4-stündiges Kaninchenloch voller Forschungswut. Gerne meine geistige Gesundheit auf Kosten meines Stolzes wiederherstellen.
Seth Bro
1

Für Mitbenutzer von Garnarbeitsbereichen ist hier meine Situation und wie ich es herausgefunden habe.

Die Facebook-Dokumente zu Invalid Hook Call Warning sagen nichts über Garnarbeitsbereiche aus, daher nahm ich an, dass meine Konfiguration korrekt war. Aber es war nicht so. Sie können den Fehler nur beheben, indem Sie für alle Pakete dieselbe Version verwenden .

Im obigen Beispiel müssen Sie die Version von react von "foo" auf 16.10.1 erhöhen, damit sie mit der React-Version von "bar" übereinstimmt.

Bonus: In dieser Diskussion auf GitHub finden Sie eine schöne Sammlung von emotionalem Gepäck, das im Internet abgeladen wurde.

Paul Razvan Berg
quelle
0

Wenn Sie die Create React App verwenden, müssen Sie die "react-scripts"Version auch mit der React- und React -Dom-Version aktualisieren .

 "react-scripts": "2.1.5",
 "react": "^16.8.1",
 "react-dom": "^16.8.1",

Diese Kombination funktioniert gut.

kartikag01
quelle
0

Nun, in meinem Fall habe ich useSelector in useEffect aufgerufen !!

Pranay Dutta
quelle
-5

Aktualisieren Sie die React-Dom-Version von package.json als React

Shisongyan
quelle
"reagieren": "^ 16.7.0-alpha.0", "reagieren-dom": "^ 16.7.0-alpha.0",
shisongyan
5
Wenn die Antwort nur ein Vorschlag ist, können Sie den Kommentarbereich
AirCodeOne