无效的挂钩调用。钩子只能在使用 react-apollo 的函数组件内部调用
Posted
技术标签:
【中文标题】无效的挂钩调用。钩子只能在使用 react-apollo 的函数组件内部调用【英文标题】:Invalid hook call. Hooks can only be called inside of the body of a function component using react-apollo 【发布时间】:2020-02-14 01:00:06 【问题描述】:我在尝试使用来自公共 graphql api 的 react-apollo 时遇到此错误。
无效的挂钩调用。 Hooks 只能在 a 的主体内部调用 功能组件。这可能发生在以下情况之一 原因:
您的 React 和渲染器版本可能不匹配(例如 React DOM) 您可能违反了 Hooks 规则 您可能在同一个应用中拥有多个 React 副本
我已阅读 react documentations,我确信问题不是这三个原因之一。
这是一个使用create-react-app
的简单项目。 react
和 react-dom
版本都是 16.10.2
。
app.js:
import React, useState from 'react';
import Query from "react-apollo";
import gql from "apollo-boost";
const query = gql`
countries
name
code
`;
function App()
const [country, setCountry] = useState('US');
const onCountryChange = event =>
setCountry(event.target.value);
;
return (
<div className="App">
<Query query=query>
result =>
if (result.loading) return <p>Loading...</p>;
if (result.error) return <p>result.error.message</p>;
return (
<select value=country onChange=onCountryChange>
result.data.countries.map(country => (
<option key=country.code value=country.code>
country.name
</option>
))
</select>
);
</Query>
</div>
);
export default App;
index.js:
import React, useState from 'react';
import ReactDOM from 'react-dom';
import App from "./app";
import ApolloClient from 'apollo-boost';
import ApolloProvider from "react-apollo";
const client = new ApolloClient(
uri: 'https://countries.trevorblades.com'
);
ReactDOM.render(
<ApolloProvider client=client>
<App />
</ApolloProvider>,
document.getElementById("root")
);
我是 graphql 和 apollo 的新手,不知道这个错误可能是什么原因。
更新
正如@Joseph 建议的那样,我从应用程序中提取了一个组件并使用了useQuery
,现在代码如下所示:
选择.js:
import React, useState from 'react';
function Select(props)
const [country, setCountry] = useState('US');
const onCountryChange = event =>
setCountry(event.target.value); // already called within the function component
;
return (
<select value=country onChange=onCountryChange>
props.countries.map(country => (
<option key=country.code value=country.code>
country.name
</option>
))
</select>
);
export default Select;
app.js:
import React from 'react';
import Query from "react-apollo";
import gql from "apollo-boost";
import useQuery from '@apollo/react-hooks';
import Select from './select';
const query = gql`
countries
name
code
`;
function App()
const loading, error, data = useQuery(query);
return (
<div className="App">
<>
loading && <p>Loading...</p>
error && <p>error.message</p>
<Select countries=data.countries />
</>
</div>
);
export default App;
index.js
没有变化,但我仍然遇到同样的错误。
更新 2:
我错过了安装@apollo/react-hooks
,但是当我安装它时,我现在遇到了一个新错误:
在上下文中找不到“客户端”或作为选项传入。裹 中的根组件,或传递 ApolloClient 通过选项中的实例。
更新 3:
这有点长,但我已将 ApolloProvider
from @apollo/react-hooks
导入 index.js
以修复最后一个问题:
import ApolloProvider from "@apollo/react-hooks";
现在我明白了
类型错误:数据未定义
在这行来自app.js
:
<>
loading && <p>Loading...</p>
error && <p>error.message</p>
<Select countries=data.countries /> // <= This line causes error
</>
【问题讨论】:
您提供的第一个代码没有任何问题。如果你有错误,它在其他地方。这是在代码框中运行良好的完全相同的代码:codesandbox.io/s/confident-snowflake-kdyik @MarouaneFazouane 但到目前为止,这就是所有项目,codesandbox 可能与create-react-app
有所不同吗?
我不这么认为。尝试停止然后重新运行yarn start
或其他什么?
@MarouaneFazouane 这给我留下了更新 2 中的第二个错误
@AlexJolig 没关系。我不觉得显示长答案。大声笑无论如何,这条线基本上是conditional render。需要确保data
和 data.countries
都已定义(非空)才能呈现Select
组件。很高兴知道现在一切都很好。
【参考方案1】:
我在使用 react-apollo 时遇到了这个错误
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:You might have mismatching versions of React and the renderer (such as React DOM)You might be breaking the Rules of HooksYou might have more than one copy of React in the same app
所以我已经修复如下代码所示:
Home.js
import useLazyQuery, useMutation from '@apollo/client'
import React, useEffect, useState from 'react'
import GET_ALL_PROJECTS from '../graphql/Queries'
function Home()
const [getEmployees, loading, data, error ] = useLazyQuery(GET_ALL_PROJECTS,
variables:
);
if (error)
console.log(error)
if (data)
console.table(data)
useEffect(() =>
getEmployees();
, []);
return (
<div className="home">...</div>
export default Home
【讨论】:
以上是关于无效的挂钩调用。钩子只能在使用 react-apollo 的函数组件内部调用的主要内容,如果未能解决你的问题,请参考以下文章
错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 【我还在用函数组件】
错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 (React-hooks React-native)