如何在第一次渲染和点击时都渲染 useQuery? [ReactJS,graphql]
Posted
技术标签:
【中文标题】如何在第一次渲染和点击时都渲染 useQuery? [ReactJS,graphql]【英文标题】:How to render useQuery both on first render and onclick? [ReactJS, graphql] 【发布时间】:2020-10-16 15:46:12 【问题描述】:如何让我的 useQuery() 在第一次渲染以及后续事件(例如按钮单击)时触发?
根据我的阅读,当 React 首次挂载一个调用 useQuery
的组件时,Apollo 会自动执行查询,如果我想执行该查询以响应事件,我可以改为使用useLazyQuery
返回一个可以调用的函数。如果我想两者都做怎么办?
不太确定我对 React 钩子的哪一部分理解不正确或不完整,但我尝试在 useQuery
中使用 refetch
,这绝对允许我调用该函数,但似乎并不总是在组件安装时触发(更令人困惑的是,有时会,有时不会)。我也在使用notifyOnNetworkStatusChange
,我读到它需要refetch
来识别它应该触发useQuery
的onCompleted
部分。
任何帮助将不胜感激,我想我根本不了解 Hooks。谢谢!
附:我的useQuery
的一个例子如下:
const refetch: refetchGetTaskTypes = useQuery(GET_TASK_TYPES(["taskId", "taskType"]),
notifyOnNetworkStatusChange: true,
onCompleted: (data) =>
if (data !== undefined && data.getTaskTypes !== undefined && data.getTaskTypes !== state.taskTypes)
dispatch(
type: 'GET_TASK_TYPES',
payload:
taskTypes: data.getTaskTypes
);
);
附言作为refetch
的示例,有时需要调用来渲染而其他时候不需要,我有另一个useQuery
,它与上面几乎相同(使用不同的查询)也有refetch
,但它首先呈现加载
P.P.P.S.我有时会看到refetch
获取过时数据的另一个问题,我必须使用fetchPolicy: 'cache-and-network'
来修复它。然而,这并不总是发生
【问题讨论】:
使用 useLazyQuery,然后在 useEffect(()->,[]) 中调用它,它将处理您的初始负载。 【参考方案1】:,但我尝试在 useQuery 中使用 refetch,这绝对允许我调用该函数,但似乎并不总是在组件挂载时触发(更令人困惑的是,有时它会,有时它不会' t)
我怀疑
...网络请求没有被触发? ...或者您的onCompleted
条件不满足(那么没有dispatch
)?没有dispatch
并不意味着没有请求/解雇...
onCompleted: (data) =>
if (data !== undefined && data.getTaskTypes !== undefined && data.getTaskTypes !== state.taskTypes)
也许你可以删除所有条件:
当data
存在时,onCompleted
被触发,无需测试它(data !== undefined
)
getTaskTypes
可以为空吗?如果不是(恕我直言,它不应该),也不要测试它;
data.getTaskTypes !== state.taskTypes
- 为什么不只针对这种类型询问 API?不支持过滤?
你的代码有点混乱
useQuery(GET_TASK_TYPES(["taskId", "taskType"])
它看起来像一些生成器/函数(定义必填字段?) - 改用 const。
还原
看起来您正在使用 redux 来存储接收到的数据。 Apollo 更加智能(规范化缓存)并且不需要为每个数据 [type] 获取编写自定义操作。您应该为此使用 Apollo,但可能您对其进行了测试但失败了? ...
缺少id
字段?
您的任务没有id
字段而是taskId
? Apollo 不会将其写入缓存。幸运的是,您可以帮助 Apollo 识别您数据中的唯一标识符 - https://www.apollographql.com/docs/react/caching/cache-configuration/#custom-identifiers
在此之后,您可以简单地使用来自useQuery
的data
进行第一次渲染,并在需要/来自事件处理程序时使用refetch
(不使用useEffect
挂钩)。
【讨论】:
嗨@xadm,感谢您的回复!我检查了我的 onCompleted (它甚至不会在 if 语句之外触发)。 “请求这种类型的 API”是什么意思?如果这很重要,我正在使用打字稿,所以我需要手动检查类型(否则似乎无法编译)。也不确定“使用 const”是什么意思?最后,关于使用data
和refetch
,如何使用refetch
更新data
变量?我已经测试过,data
似乎没有更新来自新查询的信息。谢谢!
抱歉忘了说:我没有使用 Redux,我使用的是 Apollo Store。我有一个使用调度解析器等定义的 Store.tsx!
您不应该检查 onCompleted 触发,而是在浏览器开发工具中检查 RAW/JSON 网络请求/响应 .... 要求 API 仅返回某些任务类型(如果有更多任务类型)...如果是一个打字稿,那么您应该使用键入的useQuery
来定义响应数据类型,而不是通过代码检查它... data
应该再次更改,检查网络响应...阿波罗存储?文档/示例?
我也在浏览器中检查了网络,后端数据在那里是正确的,data
不匹配
恕我直言,您应该使用 fetchPolicy: "network-only"
进行此查询【参考方案2】:
使用 LazyQuery -
const [getTaskType, loading, data ] = useLazyQuery(GET_TASK_TYPE, fetchPolicy: 'network-only'); // fetch policy is to not look for cache and take the data from network only
获取页面加载数据 -
useEffect(() =>
getTaskType();
, []);
要随时在按钮单击时触发它,您只需调用该方法即可。 -
<Button
onClick=()=>getTaskType()>Click Me!
</Button>
【讨论】:
谢谢@Dlucidone!这是推荐的方式吗?另外,它是否“反对”任何类型的 react-hooks 规则?据我了解,在钩子中你并没有真正“调用”钩子本身以上是关于如何在第一次渲染和点击时都渲染 useQuery? [ReactJS,graphql]的主要内容,如果未能解决你的问题,请参考以下文章
react-query:useQuery 返回 undefined 并且组件不会重新渲染