当来自 Apollo useQuery 挂钩的“数据”返回 useMemo 所依赖的“数据”的新值时,useMemo 未运行
Posted
技术标签:
【中文标题】当来自 Apollo useQuery 挂钩的“数据”返回 useMemo 所依赖的“数据”的新值时,useMemo 未运行【英文标题】:useMemo not running when "data" from Apollo useQuery hook returns a new value for "data" on which useMemo is dependent 【发布时间】:2021-10-21 12:06:48 【问题描述】:我有一个组件,它使用 useQuery Apollo Hook 从 GraphQL API 获取数据。该组件还有一个 useMemo,它具有从 useQuery Apollo 挂钩返回的数据变量作为依赖项。 useMemo 最初在组件的第一次渲染上运行,因为它应该。然后,当来自 useQuery 的数据返回时,它再次运行。我通过对 useQuery 中的数据变量进行一些更改来跟进这一点。
现在,当我在另一个选项卡中重新渲染此组件时,useQuery 在初始渲染时运行一次,这是应该的,但当来自 useQuery 的数据返回时不会再次运行。 注意:我在上一个选项卡中修改了 useMemo 中的数据变量,graphql api 返回了一个新的数据值,所以 useMemo 应该能够发现它,但不知何故它没有。
我调查的可能原因:
-
useMemo 只会在第二个选项卡中第二次运行,如果“数据”变量处于函数状态,并且当来自 useQuery 的新数据返回并且 useQuery 重新呈现组件时不会运行,因为它没有变化的可见性。
任何帮助将不胜感激。谢谢!
functional component:
const data, loading, error: loadRolesError = useQuery();
const result = useMemo(()=>
// changing data inside here
, [data])
【问题讨论】:
什么?使用效果,不是备忘录...单独的选项卡=单独的状态/实例...您无法更改加载的数据,apollo返回只读数据...准备更真实和可编辑的minimal reproducible example和更详细的描述? 嘿,谢谢你回来 - 我找到了问题,错误的原因如下 - 我的组件中发生的问题是我正在更改从 useQuery 返回的“数据”值直接在我的组件逻辑中挂钩。 useMemo 没有运行是因为改变了“数据”,这是一个直接在 React 知识之外的状态变量。而且我还确认 useQuery 在数据更改时成功地重新渲染了我的组件。 并且单独的选项卡共享相同的状态,因为数据是一个对象并且它们是通过引用复制的。我直接修改它而不使用useEffect。所以它被分享了。 【参考方案1】:我会在这个用例中使用 Apollo 的 useReactiveVar 钩子。来自文档With the useReactiveVar hook, React components can also include reactive variable values in their state directly, without wrapping them in a query.
这有几个部分,所以我在下面草拟了一个解决方案,它为所有部分提供了导入声明和从依赖项开始的可能实现
import React, useEffect, useState, useMemo from 'react';
import useReactiveVar, makeVar, useLazyQuery, InMemoryCache from "@apollo/client";
制作 apollo 缓存变量
export const dataWillUpdate =
// some nice flat schema data object,
niceFlatSchemaData:
;
const dataWillUpdateVar = makeVar(dataWillUpdate);
const component = () =>
// make the reactive apollo variable
const dataWillUpdateVarReactive = useReactiveVar(dataWillUpdateVar);
// memo the niceFlatSchemaData data object
const niceFlatSchemaData = useMemo(() => userProfileVarReactive.niceFlatSchemaData, [
dataWillUpdateVarReactive.niceFlatSchemaData,
]);
// see 2 for lazy queries
const [ getData, data, loading, error: loadRolesError ] = useLazyQuery();
useEffect(() =>
// will update here when change to niceFlatSchemaData
// so run query here
getData(variables:input:
// nice flat input object for the gql
)
, [niceFlatSchemaData])
useEffect(() =>
// will update here when quer calls back
// state changes for render
, [data])
需要在 apollo 缓存中配置变量
const globalCache = new InMemoryCache(
typePolicies:
Query:
fields:
dataWillUpdate:
read()
return dataWillUpdateVar();
,
,
,
,
,
);
[1]useReactiveVar [2]lazy query
【讨论】:
感谢您的详细回复。我的组件中发生的问题是我直接在我的组件逻辑中更改了从 useQuery 挂钩返回的“数据”值。 useMemo 没有运行是因为改变了“数据”,这是一个直接在 React 知识之外的状态变量。而且我还确认 useQuery 在数据更改时成功地重新渲染了我的组件。以上是关于当来自 Apollo useQuery 挂钩的“数据”返回 useMemo 所依赖的“数据”的新值时,useMemo 未运行的主要内容,如果未能解决你的问题,请参考以下文章
Apollo 客户端没有读取使用 useQuery 钩子传入的变量
Apollo 客户端 fetchMore 来自 useQuery 触发两个网络请求
无法使用 useQuery 挂钩为具有一些 @client 变量的远程查询获取数据
来自 apollo react 的 useQuery 方法的意外结果