如何在第一次渲染和点击时渲染 useQuery?[ReactJS,graphql]

IT技术 reactjs graphql react-hooks
2021-05-09 09:15:34

如何让我的 useQuery() 在第一次渲染以及后续事件(例如按钮单击)上触发?

从我读过的内容来看,当 React 挂载useQuery第一次调用 a 的组件时,Apollo 会自动执行查询,如果我想执行该查询以响应事件,我可以改用useLazyQuerywhich 返回一个函数,该函数可以叫做。如果我想两者都做怎么办?

不太确定我对 React 钩子的理解中哪一部分不正确或不完整,但我尝试使用refetchin useQuery,这绝对允许我调用该函数,但似乎并不总是在组件安装时触发(更令人困惑的事情是有时会,有时不会)。我还使用notifyOnNetworkStatusChange,这是我读它需要refetch认识到它应该触发onCompleted的一部分useQuery

任何帮助将不胜感激,我想我根本不了解 Hooks。谢谢!

PS我的一个例子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
                }
            });
        }
    }
});

PPS 作为一个例子,refetch有时需要被调用来渲染,有时不需要,我有另一个useQuery与上面几乎相同的(具有不同的查询),它也有refetch,但它在第一次加载时呈现

PPPS 我有时会看到另一个问题,即refetch获取过时的数据,我必须使用fetchPolicy: 'cache-and-network'它来修复它。然而,它并不总是发生

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>

,但我已经尝试在 useQuery 中使用 refetch,这绝对允许我调用该函数,但似乎并不总是在组件安装时触发(更令人困惑的是,有时会,有时不会)

我怀疑

...网络请求没有被触发?......或者你的onCompleted条件不满足(不dispatch那么)?没有dispatch不等于不要求/发射...

onCompleted: (data) => {
    if (data !== undefined && data.getTaskTypes !== undefined && data.getTaskTypes !== state.taskTypes) {

可能您可以删除所有条件:

  • onCompleteddata存在时触发,无需测试 ( data !== undefined)
  • getTaskTypes可以为空吗?如果不是(恕我直言不应该),也不要测试它;
  • data.getTaskTypes !== state.taskTypes- 为什么不只要求这种类型的 API?不支持过滤?

你的代码有点混乱

useQuery(GET_TASK_TYPES(["taskId", "taskType"])

它看起来像一些生成器/函数(定义必需的字段?) - 使用 const 代替。

终极版

看起来您正在使用 redux 来存储接收到的数据。Apollo 更智能(标准化缓存)并且不需要为每个数据 [类型] 获取编写自定义操作。您应该为此使用 Apollo,但您可能对其进行了测试并失败了?...

缺少id字段?

您的任务没有id字段,但是taskId? Apollo 不会将其写入缓存。幸运的是,您可以帮助 Apollo 识别数据中的唯一标识符 - https://www.apollographql.com/docs/react/caching/cache-configuration/#custom-identifiers

在此之后,您可以简单地使用datafromuseQuery进行第一次渲染和refetch按需/来自事件处理程序(不使用useEffect钩子)。