[英]Invalid hook call. Hooks can only be used inside of a react function component... useEffect, redux
I encountered a problem with my react application related to hooks.我的 React 应用程序遇到了与钩子相关的问题。 Technologies being used: React, Redux, Apollo, ChakraUI.使用的技术:React、Redux、Apollo、ChakraUI。
Here is the React component that is troubling me:这是困扰我的 React 组件:
import React, { useEffect } from "react";
import { Flex, Container, Heading, Text } from "@chakra-ui/react";
import { connect, useSelector, useDispatch } from "react-redux";
import { State } from "../state/store";
import { fetchRecipes } from "../state/recipe/actions";
interface RecipesListProps {}
const RecipesList: React.FC<RecipesListProps> = ({}) => {
const recipes = useSelector<State>(
(state) => state.recipe.recipes
) as State["recipe"]["recipes"];
const loading = useSelector<State>(
(state) => state.recipe.loading
) as State["recipe"]["loading"];
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchRecipes());
}, []);
if (loading) {
return <h1>Loading....</h1>;
}
return (
<Flex
m="auto"
mt="5rem"
w="50%"
direction="column"
justifyContent="center"
alignItems="center"
>
<Heading>Your Recipes</Heading>
<Flex mt="2rem" direction="column" w="100%" padding="0" gridGap="2rem">
{recipes &&
recipes.map((recipe) => (
<Container
key={recipe.id}
bg="orange.100"
borderRadius="0.2rem"
padding="1rem"
maxW="100%"
>
<Text fontSize="xl" fontWeight="bold">
{recipe.title}
</Text>
<Text>{recipe.description}</Text>
</Container>
))}
</Flex>
</Flex>
);
};
export default RecipesList;
Notice the use of the useEffect()
hook.注意useEffect()
钩子的使用。 This is the error I am getting:这是我得到的错误:
Error: 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:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
I am pretty sure I am disobeying rule number, 2 ie I am breaking the Rules of Hooks.我很确定我违反了规则编号 2,即我违反了 Hooks 规则。 As soon as I take the useEffect()
call out of the component, it doesn't throw an error.一旦我从组件中取出useEffect()
调用,它就不会抛出错误。
Could someone please give some guidance as to what I am doing wrong?有人可以就我做错了什么提供一些指导吗? Thanks.谢谢。
Edit:编辑:
The fetchRecipes
function is a Redux thunk function that fetches recipes from a graphql server fetchRecipes
函数是一个 Redux thunk 函数,用于从 graphql 服务器获取配方
Update:更新:
I have been hacking away at a solution to this problem.我一直在破解这个问题的解决方案。 I replaced the dispatch(fetchRecipes())
call with a console.log("hello world")
, and it worked perfectly!我用console.log("hello world")
替换了dispatch(fetchRecipes())
调用,它工作得很好!
This is boggling my mind!这让我大吃一惊! Is this a problem with the fetchRecipes
function?这是fetchRecipes
函数的问题吗?
Edit:编辑:
Here's the code for the fetchRecipes
function:这是fetchRecipes
函数的代码:
export const fetchRecipes = () => {
return (dispatch: Dispatch) => {
dispatch(fetchRecipesPending());
const { data } = useRecipesQuery();
const errors = data?.recipes.errors;
const recipes = data?.recipes.recipes;
if (errors?.length) {
dispatch(fetchRecipesFailure(errors));
} else {
dispatch(fetchRecipesSuccess(recipes));
}
};
};
useRecipesQuery
is a custom hook that was auto generated using the graphql-codegen
library. useRecipesQuery
是一个使用graphql-codegen
库自动生成的自定义钩子。 It builds up on the useQuery
hook from the @apollo/client
library.它建立在来自@apollo/client
库的useQuery
钩子上。
Your useEffect
needs a little rewrite.您的useEffect
需要稍微重写一下。 You are dispatching the function fetchRecipes
which in itself is a hook, but the thing dispatched should be a plain "action" (using Redux terminology here).您正在调度函数fetchRecipes
,它本身就是一个钩子,但调度的东西应该是一个简单的“动作”(这里使用 Redux 术语)。 So I guess we can fix that by breaking up your fetchRecipes fn.所以我想我们可以通过分解你的 fetchRecipes fn 来解决这个问题。
A snippet of the component would now look like following:组件的一个片段现在看起来像下面这样:
const { data } = useRecipesQuery();
useEffect(() => {
if (!data) {
dispatch(fetchRecipesPending()) // I only assume you fetch on render
}
if (data?.recipes?.errors) {
dispatch(fetchRecipesFailure(data?.recipes.errors)
}
if (data?.recipes?.recipes) {
dispatch(fetchRecipesSuccess(data?.recipes?.recipes)))
}
}, [data]);
Now it should be fine AND more readable.现在它应该没问题并且更具可读性。 Either way, as some has already suggested, I would think about using some more standardised way like using Redux w/ Thunks or Sagas, or, even better - I see you might be doing a GQL query - if so, just use a hook for it and handle the data with Apollo Client.无论哪种方式,正如一些人已经建议的那样,我会考虑使用一些更标准化的方式,例如使用 Redux w/Thunks 或 Sagas,或者甚至更好 - 我看到您可能正在执行 GQL 查询 - 如果是这样,只需使用一个钩子它并使用 Apollo Client 处理数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.