无效的挂钩调用。钩子只能在反应函数组件内部使用...... useEffect,redux
Posted
技术标签:
【中文标题】无效的挂钩调用。钩子只能在反应函数组件内部使用...... useEffect,redux【英文标题】:Invalid hook call. Hooks can only be used inside of a react function component... useEffect, redux 【发布时间】:2021-12-26 13:30:43 【问题描述】:我的 react 应用程序遇到了与钩子相关的问题。使用的技术:React、Redux、Apollo、ChakraUI。
这是困扰我的 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;
注意useEffect()
钩子的使用。这是我得到的错误:
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
我很确定我违反了规则编号 2,即我违反了 Hooks 规则。一旦我从组件中取出useEffect()
调用,它就不会引发错误。
有人可以就我做错了什么提供一些指导吗? 谢谢。
编辑:
fetchRecipes
函数是一个 Redux thunk 函数,它从 graphql 服务器获取食谱
更新:
我一直在想办法解决这个问题。我用console.log("hello world")
替换了dispatch(fetchRecipes())
调用,效果很好!
这让我大吃一惊!这是fetchRecipes
函数的问题吗?
编辑:
这是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
是使用graphql-codegen
库自动生成的自定义挂钩。它建立在 @apollo/client
库中的 useQuery
钩子之上。
【问题讨论】:
fetchRecipes
是做什么的?
我添加了fetchRecipes
函数的小描述。如果您需要了解更多信息,请告诉我...非常感谢!
顺便说一下,我没有在这个项目中使用 Redux Toolkit,只是让你知道
请分享fetchRecipes
的实际代码。我打赌你在那里使用了一个钩子,因此违反了钩子的规则。题外话,你真的应该使用 Redux Toolkit。多年来,它是每个 Redux 代码的官方推荐。
其实我在fetchRecipes
中使用了一个钩子!我会马上分享它的代码!
【参考方案1】:
您的useEffect
需要稍作改写。您正在调度函数fetchRecipes
,它本身就是一个钩子,但调度的东西应该是一个简单的“动作”(在此处使用 Redux 术语)。所以我想我们可以通过分解你的 fetchRecipes fn 来解决这个问题。
组件的 sn-p 现在如下所示:
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]);
现在它应该没问题并且更具可读性。无论哪种方式,正如一些人已经建议的那样,我会考虑使用一些更标准化的方式,比如使用带有 Thunks 或 Sagas 的 Redux,或者,甚至更好——我看到你可能正在做一个 GQL 查询——如果是这样,只需使用一个钩子它并使用 Apollo Client 处理数据。
【讨论】:
以上是关于无效的挂钩调用。钩子只能在反应函数组件内部使用...... useEffect,redux的主要内容,如果未能解决你的问题,请参考以下文章
错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 【我还在用函数组件】
× 错误:无效的挂钩调用。 Hooks 只能在函数组件的主体内部调用。[ReactJS]
错误:无效的挂钩调用。钩子只能在函数组件的主体内部调用。 (React-hooks React-native)