React-Query结合graphql-request引发不必要重渲染问题求助
解决Login组件不必要重渲染的方案
问题根源分析
你的组件出现重复渲染,核心原因有两个:
- 每次组件渲染时,都会创建新的
headers对象和useGQLQuery内部的fetchData函数,导致React Query的useQuery钩子检测到依赖变化,重复发起请求,进而触发组件重渲染。 useGQLQuery钩子中,每次调用都新建GraphQLClient实例,没有对查询函数和客户端实例做稳定化处理,导致useQuery频繁触发查询更新。
具体修复步骤
1. 稳定化组件内的headers对象
在Login组件中,用useMemo缓存headers,避免每次渲染生成新对象:
// 替换原headers定义 const headers = useMemo(() => ({ headers: { "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJFbWFpbCI6Im15ZW1haWwxQGVtYWlsLmNvbSIsIlVzZXJJZCI6IjFhYjk1YTc5LTQwMGMtNDkzZi04YjdiLTY1MzQzMzg2YjI5OCIsImV4cCI6MTY5OTI3MTIyNCwidG9rZW5fdHlwZSI6ImFjY2VzcyJ9.UMtJxGeijalrH4NFv0V7ITplI4s5otIBFLIrHYdAP9U" } }), []);
2. 优化useGQLQuery钩子,稳定查询依赖
修改自定义钩子,用useMemo缓存GraphQLClient实例,用useCallback稳定查询函数,确保只有依赖变化时才更新:
import { useQuery, useMemo, useCallback } from "react-query"; import { GraphQLClient } from "graphql-request"; const API_URL = "http://localhost:8080/query"; export const useGQLQuery = (key, query, variables, headers = {}, config = {}) => { // 缓存GraphQLClient,仅在headers变化时重建 const graphQLClient = useMemo(() => { return new GraphQLClient(API_URL, headers); }, [headers]); // 稳定fetchData函数,依赖client、query和variables const fetchData = useCallback(async () => { return await graphQLClient.request(query, variables); }, [graphQLClient, query, variables]); return useQuery(key, fetchData, config); };
3. 将渲染阶段的逻辑移至副作用钩子
当前组件在渲染阶段直接执行console.log和条件判断,虽然不会直接导致重渲染,但建议放到useEffect中,保持渲染阶段的纯净性:
// 在Login组件中添加useEffect useEffect(() => { if (isLoading) console.log("Loading"); if (error) console.log("React Query Error", error); if (data) { console.log("Error is ", data?.auth?.getUserDetails?.error); if (data?.auth?.getUserDetails?.error?.message != null) { console.log("Error Message", data.auth.getUserDetails.error); } console.log(data); } }, [isLoading, error, data]);
4. 正确理解React.memo的作用
React.memo仅会浅比较组件的props,避免父组件重渲染时的不必要更新。如果组件内部的hooks(比如useQuery)状态发生合法变化(比如加载完成、数据返回),组件仍会正常重渲染——这是合理行为,优化后组件只会在真正的状态变更时渲染,不会出现无意义的重复更新。
内容的提问来源于stack exchange,提问作者Vishal Regmi
相关产品推荐
相关产品推荐

