【问题标题】:How to render useQuery both on first render and onclick? [ReactJS, graphql]如何在第一次渲染和点击时都渲染 useQuery? [ReactJS,graphql]
【发布时间】:2020-10-16 15:46:12
【问题描述】:

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

根据我的阅读,当 React 首次挂载一个调用 useQuery 的组件时,Apollo 会自动执行查询,如果我想执行该查询以响应事件,我可以改为使用useLazyQuery 返回一个可以调用的函数。如果我想两者都做怎么办?

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

任何帮助将不胜感激,我想我根本不了解 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(()->{},[]) 中调用它,它将处理您的初始负载。

标签: reactjs graphql react-hooks


【解决方案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

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

【讨论】:

  • 嗨@xadm,感谢您的回复!我检查了我的 onCompleted (它甚至不会在 if 语句之外触发)。 “请求这种类型的 API”是什么意思?如果这很重要,我正在使用打字稿,所以我需要手动检查类型(否则似乎无法编译)。也不确定“使用 const”是什么意思?最后,关于使用datarefetch,如何使用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 规则?据我了解,在钩子中你并没有真正“调用”钩子本身
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-14
  • 1970-01-01
  • 1970-01-01
  • 2021-04-29
相关资源
最近更新 更多