"Error: invalid hook call" When using the hook within a function called on click of a button

"Error: invalid hook call" When using the hook within a function called on click of a button

我有一个组件,它具有关注和取消关注人员的逻辑。单击按钮时,应调用包含查询逻辑的函数。但是当我按下按钮时,它给我“错误:无效的钩子调用,钩子并且只能在函数组件的主体内部调用”

这些是我用于关注和取消关注逻辑的 2 个函数:

function onFollowingClick() {
        const {isLoading: deleteFollowerLoading} = useQuery(["deleteFollower", myFollowerId], () => {
            deleteFollower(myFollowerId)
        })
        console.log("following call")
}

function onFollowClick() {
    const {isLoading:createFollowerLoading} = useQuery("createFollower",
        createFollower()
    )

    console.log("follower call")
}

这是我调用函数的按钮,在map函数里面,你可以在onclick中看到:

return (
    <div className={root}>
        <div className={body}>
                {                       
                    myFollowers && myFollowings && !followerLoading && (
                        followersData.map((e) => {
                        return(<>
                            <div className="data">
                            <Grid  templateColumns="repeat(2, 1fr)" width="100%" alignContent="center">
                            <GridItem w="100%" >
                            <Flex 
                            mt="10px">
                                <Avatar
                                size={isTabletOrMobile ? "xs" : "sm"}
                                src={e.requested_profile.s3PicURL}
                                />
                                
                                <Text
                                w="100%"
                                wrap="off"
                                ml="5px"
                                isTruncated
                                fontSize={isTabletOrMobile ? "sm" : "md"}
                                >
                                    {e.requested_profile.Userlink}
                                </Text>
                            </Flex>
                            </GridItem>
                            <GridItem>
                                <Flex justifyContent="flex-end">
                                <Button
                                w="100px"
                                h="30px"
                                mt="8px"
                                onClick = { () => {
                                    if(myFollowings.includes(e.requested_profile.Userlink)){
                                        onFollowingClick()
                                    }
                                    else{
                                        onFollowClick()
                                    }
                                } }
                                variant={myFollowings.includes(e.requested_profile.Userlink) ? "outline" : "solid"}
                                width={isTabletOrMobile ? "50px" : "60px"}>
                                    {
                                        myFollowings.includes(e.requested_profile.Userlink) ? "Following" : "Follow"
                                    }
                                </Button>
                                </Flex>
                            </GridItem>
                            </Grid>
                            </div>
                            </>
                        ) 
                    })
                    )
                }
        </div>
    </div>

    
)

请告诉我如何解决这个错误。

这里有几个问题:

  1. 你不能在任何地方使用挂钩,除非它在顶级组件级别 (https://reactjs.org/docs/hooks-overview.html#rules-of-hooks)。

  2. 您使用 react-query 并尝试使用 useQuery 改变状态。该钩子用于获取数据。如果你想做突变,你应该使用 useMutation 钩子。但请注意,这些挂钩也应该位于顶层,您不能像我们调用常规函数那样从点击处理程序调用它。

那么,您的步骤是:

  • 使用回调和后端交互逻辑定义 useMutation 挂钩
  • 当你点击按钮时你调用 mutationFollow.mutate({ id: item.id })
  • 要在突变后使您的状态无效,您应该使用 onSuccess 回调:
onSuccess: () => {
   queryClient.invalidateQueries('followers')
},

执行您想要的操作的选项之一可能是:

const queryClient = useQueryClient()

const Component = () => {
  const { isLoading, data: followers } = useQuery('followers')
  const mutationFollow = useMutation(
    follower => {
      return axios.post('/follow', follower)
    },
    {
      onSuccess: () => {
        queryClient.invalidateQueries('followers')
      },
    },
  )

  const mutationUnfollow = useMutation(
    follower => {
      return axios.post('/unfollow', follower)
    },
    {
      onSuccess: () => {
        queryClient.invalidateQueries('followers')
      },
    },
  )

  if (isLoading) {
    return <div>Loading...</div>
  }

  return followers.map(item => (
    <div>
      <button
        onClick={() => {
          mutationFollow.mutate({ id: item.id })
        }}
      >
        Follow
      </button>
      <button
        onClick={() => {
          mutationUnfollow.mutate({ id: item.id })
        }}
      >
        Unfollow
      </button>
    </div>
  ))
}