Ошибка React Hooks: хуки можно вызывать только внутри тела функционального компонента

Я получаю эту ошибку при использовании ловушки useState. У меня есть это в базовой форме, я смотрю на реагировать на документы для справки, но все еще получаю эту ошибку. Я готов к моменту ладони лица ...

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

У меня работает ... ошибок нет ... вы обновляли до 16.7?

SakoBu 28.10.2018 04:43

Да, я сделал. Я думаю, может быть, это как-то связано с моей настройкой, но понятия не имею, что именно. Событие, если я использую тот же самый крючок в верхней части компонента функции App, я получаю ту же ошибку.

logandeancall 28.10.2018 05:08

Хммм ... все, что я сделал, это npx create-response-app newhook, а затем yarn add response @ next и react-dom @ next, и все сработало отлично ...

SakoBu 28.10.2018 05:10

Просто к сведению всех, кто здесь окажется, вам нужно обновить и React, и ReactDOM до @next, чтобы хуки работали. Если вы этого не сделаете, реакция выдаст указанную выше ошибку. Я знаю, потому что у меня только что была эта проблема, и это было моим решением.

Tony 30.10.2018 04:37
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
82
4
101 135
19
Перейти к ответу Данный вопрос помечен как решенный

Ответы 19

Ответ принят как подходящий

Обновлено: 2018-декабрь

Вышла новая версия react-hot-loader, ссылка. Хуки теперь работают из коробки. Спасибо автору Кашей.

Посмотрите этот шаблон https://github.com/ReeganExE/react-hooks-boilerplate

  • Реагировать на хуки
  • React Hot Loader
  • Webpack, Babel, ESLint Airbnb

Предыдущий ответ:

Сначала убедитесь, что вы установили react@next и react-dom@next.

Затем проверьте, используете ли вы react-hot-loader или нет.

В моем случае отключите горячий загрузчик, и HMR может заставить его работать.

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

Цитата:

Yes. RHL is 100% not compatible with hooks. There is just a few reasons behind it:

SFC are being converted to Class components. There is reason - to be able to forceUpdate on HMR, as long there is no "update" method on SFC. I am looking for other way of forcing the update (like this. So RHL is killing SFC.

"hotReplacementRender". RHL is trying to do React's job, and render the old and the new app, to merge them. So, obviously, that's broken now.

I am going to draft a PR, to mitigate both problems. It will work, but not today.

Есть более подходящее исправление, которое подействует - холодный 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 за обновление.

Спасибо, что указали на это :). Я использую response-hot-loader, поэтому было бы понятно, что он не работает. Однако я еще не уверен на 100%, что что-то еще не происходит. Я буду следить за этой проблемой в response-hot-loader и обновлю этот вопрос после публикации исправления.

logandeancall 29.10.2018 16:11

Теперь я могу подтвердить, что отключение response-hot-loader устранило эту ошибку.

logandeancall 30.10.2018 05:40

Чтобы добавить, если по какой-либо причине вы визуализируете свой компонент как встроенный вызов функции jsx, это все равно вызовет ошибку, даже если компонент заключен в cold. Таким образом, {MyComponent(props)} не будет работать, но <MyComponent {...props} /> будет.

Dimitar Nikovski 19.11.2018 11:08

Теперь есть способ заставить это работать с помощью react-hot-loader. Обратитесь к этому комментарию разработчика response-hot-loader, github.com/gaearon/react-hot-loader/issues/…

logandeancall 29.11.2018 05:23

Проблема для меня действительно была реактивно-горячий загрузчик.

Вы можете отключить react-hot-loader для одного компонента вместо всего приложения, используя метод cold, например:

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

export const YourComponent = cold(() => {

  // ... hook code

  return (
    // ...
  )
})

ИЛИ

export default cold(YourComponent)

Я смог решить эту проблему, импортировав примитивные хуки 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, что обеспечивает более естественное функциональное программирование и тестирование.

Моя проблема заключалась в том, что я забыл обновить модуль react-dom. См. Проблему.

Я тоже! Я использую приложение create-response-app и Typescript

jugglingcats 14.11.2018 20:01

Я использую response и response-dom версии 16.8.3, но все еще имею ту же проблему

huykon225 06.11.2019 15:44

У меня возникла эта ошибка при использовании Замена горячего модуля посылки, и она исправлена ​​обновлением react-dom до альфа-версии:

yarn add [email protected]

См. Эту проблему.

нашел этот обходной путь для react-hot-loader, в то время как PR для его исправления является входящим.

Оберните функцию, вызывающую хуки, в React.memo, чтобы предотвратить горячую перезагрузку, если она не изменилась.

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

Кредит для решения: https://github.com/gatsbyjs/gatsby/issues/9489

У меня была проблема в монорепозитории, где пакет docz использовал [email protected], а окончательный выходной пакет имел две версии реакции.

Проблема на Github

Исправлено удалением пакета ?

обновить версию package.json в качестве реакции

"реагировать": "^ 16.7.0-alpha.0", "react-dom": "^ 16.7.0-alpha.0",

shisongyan 28.11.2018 04:08

Если ответ - просто предложение, вы можете использовать раздел комментариев.

AirCodeOne 28.11.2018 04:15

Если вы используете приложение Create React, вам необходимо обновить версию "react-scripts" также с помощью версии react и response-dom.

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

эта комбинация отлично работает.

Моя проблема заключалась в следующем:

Я делал: ReactDOM.render(Example(), app);

В то время как я должен был делать: ReactDOM.render(<Example />, app);

Это тоже была моя проблема, и я рад найти ее среди ответов здесь.

Seth Bro 20.01.2020 08:19

Это тоже была моя проблема, и я рад найти ее среди ответов здесь. Я подозревал, что это будет какая-то тонкая глупость по моей собственной инициативе, но поскольку там явно есть реальные проблемы с дублированием модулейв связках, я погрузился в 4-часовую кроличью нору исследовательской ярости. Счастлив восстановить рассудок за счет гордости.

Seth Bro 20.01.2020 08:32

Была такая же проблема. Моя проблема была связана с React Router. Я случайно использовал

<Route render = {ComponentUsingHooks} />

вместо того

<Route component = {ComponentUsingHooks} />

этот комментарий тоже спас мне жизнь. Потратил на это 3 часа и разорвал мой проект на части. Была опечатка в роутере

Ben Gannaway 01.05.2020 17:41

Я визуализировал компонент как дочерний элемент внутри элемента Route как <Route>{component}</Route>, и решение помогло

Cea 22.01.2021 23:55

Просто потратил на это весь свой день. Спасибо!

excurbia 07.07.2021 19:15

Тем, кто сталкивается с этой проблемой при использовании MobX и упаковке компонента в observer, убедитесь, что вы используете mobx-react-lite вместо mobx-react.

ОБНОВЛЕНИЕ 29 МАЯ

Начиная с mobx-react6.0.0, компоненты на основе хуков теперь поддерживаются mobx-react, таким образом, больше нет необходимости в использовании mobx-react-lite (если это была ваша проблема).

Чтобы уточнить ответ @rista404, включая повторяющиеся версииreact (и, возможно, react-dom), вы получите ту же ошибку в зависимости от того, где вы используете свои хуки. Вот два примера ...

  1. Внешняя зависимость включает другую версию react в свой dependencies, вероятно, по ошибке, поскольку react обычно должен быть одноранговой зависимостью. Если npm не выполняет автоматическое копирование этой версии в вашу локальную версию, вы можете увидеть эту ошибку. Это то, о чем имел в виду @ rista404.
  2. Вы npm link пакет, который включает react в его devDependencies или dependencies. Теперь для модулей в этом пакете вы можете увидеть ошибки, если они извлекут другую версию react из своего локального каталога node_modules, а не из родительского проекта.

Последнее может быть исправлено при объединении с 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 (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) устранило ошибку.

Для других пользователей рабочих пространств yarn, вот моя ситуация и то, как я ее понял.

Документы Facebook на Предупреждение о недопустимом вызове трубки ничего не говорят о рабочих пространствах пряжи, поэтому я предположил, что моя конфигурация верна. Но это было не так. Вы можете исправить ошибку, только используя одну и ту же версию в все ваши пакеты.

В приведенном выше примере вы должны поднять версию response с «foo» до 16.10.1, чтобы она соответствовала версии response из «bar».

Бонус: см. это обсуждение на GitHub за красивую коллекцию эмоционального багажа, выгруженную в Интернет.

Другое решение, если вы столкнулись с этим при использовании ссылки npm:

Вы можете реагировать на npm link в своей библиотеке, как описано здесь: https://reactjs.org/warnings/invalid-hook-call-warning.html#duplicate-react

или установите реакцию в своей библиотеке как peerDependency, а затем используйте npm link --only=production

Что ж, в моем случае я вызывал useSelector внутри useEffect !!

ОТВЕТ ИЮНЯ 2021 ГОДА

У меня возникла эта проблема с приложением реагировать-электрон-шаблон.

Многие плагины и библиотеки, такие как Material-UI, не могли быть использованы в моем проекте из-за этой досадной ошибки, и после долгих поисков я смог решить проблему:

Я только что обновил react и react-dom до последних версий.

Эта команда выполнила свою работу!

yarn add react@latest react-dom@latest

Убедитесь, что версии react и react-dom - строго равный. Обратите внимание на символ циркумфлекса ^ на версиях.

"17.0.0" не может быть таким же, как "^17.0.0"

npm - диапазоны Carret: https://github.com/npm/node-semver#caret-ranges-123-025-004 Реагировать - Список изменений: https://github.com/facebook/react/blob/main/CHANGELOG.md

Это одна из причин, по которой лучше устанавливать пакеты с -E или --save-точным.

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

Другие вопросы по теме