簡體   English   中英

React Hooks 錯誤:只能在函數組件內部調用 Hooks

[英]React Hooks Error: Hooks can only be called inside the body of a function component

使用useState掛鈎時出現此錯誤。 我有它的基本形式,查看反應文檔以供參考,但仍然收到此錯誤。 我已經准備好迎接面掌時刻了...

export function Header() {
  const [count, setCount] = useState(0)
  return <span>header</span>
}

更新時間:2018-12 月

新版本的react-hot-loader現已發布, 鏈接 Hooks 現在可以開箱即用了。 感謝作者,theKashey。

看看這個樣板https://github.com/ReeganExE/react-hooks-boilerplate

  • 反應鈎子
  • 反應熱加載器
  • Webpack、Babel、ESLint Airbnb

上一個答案:

首先,確保你安裝了react@nextreact-dom@next

然后檢查您是否正在使用react-hot-loader

在我的情況下,禁用熱加載器和 HMR 可以讓它工作。

請參閱https://github.com/gaearon/react-hot-loader/issues/1088

引:

是的。 RHL 與鈎子 100% 不兼容。 這背后有幾個原因:

SFC 正在轉換為 Class 組件。 有理由 - 能夠在 HMR 上強制更新,只要 SFC 上沒有“更新”方法。 我正在尋找強制更新的其他方式(就像這樣。所以 RHL 正在殺死 SFC。

“熱替換渲染”。 RHL 正在嘗試做 React 的工作,渲染新舊應用程序,合並它們。 所以,顯然,現在已經壞了。

我將起草一份 PR,以緩解這兩個問題。 它會起作用,但不是今天。

有一個更合適的修復方法,它可以工作 - 冷 API

您可以為任何自定義類型禁用 RHL。

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

cold(MyComponent);

在組件源代碼中搜索"useState/useEffect" ,並“冷”它。

更新:

根據 react-hot-loader 維護者的更新,您可以嘗試react-hot-loader@next並將配置設置如下:

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

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

感謝@loganfromlogan 的更新。

我的問題是忘記更新react-dom模塊。 見問題

有同樣的問題。 我的問題與 React Router 相關。 我不小心使用了

<Route render={ComponentUsingHooks} />

代替

<Route component={ComponentUsingHooks} />

我能夠通過在組件文件中導入 React 的原始鈎子,然后將它們傳遞到我的自定義鈎子中來解決這個問題。 出於某種原因,只有在我的自定義鈎子文件中導入 React 鈎子(如 useState)時才會發生錯誤。

我在我的組件文件中導入 useState:

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});
    ...
}

然后在我的鈎子文件中:

// 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];
}

這種方法提高了我的鈎子的可測試性,因為我不需要模擬 React 的庫來提供原始鈎子。 相反,我們可以將模擬useState鈎子直接傳遞到自定義鈎子的函數中。 我認為這提高了代碼質量,因為您的自定義鈎子現在與 React 庫沒有耦合,允許更自然的函數式編程和測試。

我在使用Parcel 的 Hot Module Replacement時遇到了這個錯誤,並通過將react-dom更新為它的 alpha 版本來修復:

yarn add react-dom@16.7.0-alpha.0

看到這個問題。

我在 monorepo 中遇到了問題,其中一個包docz使用了react@16.6.3 ,最終輸出包有兩個 react 版本。

Github 上的問題

通過刪除包來修復它😅

只是為了詳細說明@rista404 的答案,包括react (可能還有react-dom )的重復版本將產生相同的錯誤,具體取決於您使用鈎子的位置。 這里有兩個例子...

  1. 外部依賴性包括另一版本的react在其dependencies ,這可能誤作為react通常應該是對等的依賴。 如果npm沒有自動使用您的本地版本對此版本進行重復數據刪除,您可能會看到此錯誤。 這就是@rista404 所指的。
  2. npm link一個包,該包在其devDependenciesdependencies中包含react 現在,對於此包中的模塊,如果它們從其本地node_modules目錄而不是父項目的目錄中提取不同版本的react ,您可能會看到錯誤。

后者可以用捆綁在固定webpack使用resolve.alias是這樣的...

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

這將確保react總是從父項目的拉動node_modules目錄。

我的問題確實是react-hot-loader

您可以使用像這樣的cold方法為單個組件而不是整個應用程序禁用 react-hot-loader

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

export const YourComponent = cold(() => {

  // ... hook code

  return (
    // ...
  )
})

或者

export default cold(YourComponent)

對於那些誰碰到這個問題來使用MobX和包裝用零部件時observer ,請確保您使用mobx-react-lite ,而不是mobx-react

5 月 29 日更新

mobx-react 6.0.0開始, mobx-react 現在支持基於鈎子的組件,因此,不再需要使用mobx-react-lite (如果那是您的問題)。

如果您在使用 npm 鏈接時遇到此問題,則另一種解決方案:

您可以按照此處的說明在庫中進行npm link react: https : //reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react

或者在你的庫中將 react 設置為 peerDependency 然后使用npm link --only=production

react-hot-loader找到了這個解決方法,而修復它的 PR 是入站的。

將調用鈎子的函數包裝在React.memo ,如果它沒有改變,則防止熱重載。

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

解決方案信用: https : //github.com/gatsbyjs/gatsby/issues/9489

我的問題如下:

我在做: ReactDOM.render(Example(), app);

而我應該做的是: ReactDOM.render(<Example />, app);

對於紗線工作區的其他用戶,這是我的情況以及我是如何解決的。

  • 包裹
      • 反應@16.8.6
    • 酒吧
      • 反應@16.10.1

Invalid Hook Call Warning上的 Facebook 文檔沒有提到紗線工作區,所以我認為我的配置是正確的。 但事實並非如此。 您只能通過在所有包中使用相同的版本來修復錯誤。

在上面的示例中,您必須將 react 版本從“foo”提升到 16.10.1,以便它與“bar”中的 react 版本匹配。

獎勵:請參閱 GitHub 上的此討論,了解在 Internet 上卸下的一組精美的情感包袱。

好吧,在我的情況下,我在 useEffect 中調用 useSelector !

如果您正在使用 Create React App,您還必須使用 react 和 react-dom 版本更新"react-scripts"版本。

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

這種組合效果很好。

對我來說,這是因為我有一個新版本的 react (16.8.6) 和一個舊版本的 react-dom (16.6.1)。

https://reactjs.org/warnings/invalid-hook-call-warning.html#mismatching-versions-of-react-and-react-dom

將兩者都升級到 @latest (16.8.6) 修復了錯誤。

2021 年 6 月答案

我一直在使用react-electron-boilerplate應用程序遇到這個問題。

由於這個不幸的錯誤,許多插件和庫(如 Material-UI)無法在我的項目中使用,經過大量搜索,我可以解決問題:

我剛剛將reactreact-dom升級到了最新版本。

這個命令完成了工作!

yarn add react@latest react-dom@latest

檢查reactreact-dom版本嚴格相等 注意版本上的抑揚符^符號。

"17.0.0"不能與"^17.0.0"相同

npm - Carret 范圍: https : //github.com/npm/node-semver#caret-ranges-123-025-004 React - 變更日志: https : //github.com/facebook/react/blob/main/CHANGELOG。醫學博士

這是使用 -E 或 --save-exact 更好地安裝軟件包的原因之一

npm install --save --save-exact <package@vesion>

將 package.json react-dom 版本更新為 react

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM