【问题标题】:Trying call useQuery in function with react-apollo-hooks尝试使用 react-apollo-hooks 在函数中调用 useQuery
【发布时间】:2019-11-19 17:38:02
【问题描述】:

我想在需要时调用 useQuery,

但是useQuery不能在函数内部。

我的尝试代码是:

export const TestComponent = () => {
...
  const { data, loading, error } = useQuery(gql(GET_USER_LIST), {
    variables: {
      data: {
        page: changePage,
        pageSize: 10,
      },
    },
  })
  ...
  ...
  const onSaveInformation = async () => {
    try {
      await updateInformation({...})
      // I want to call useQuery once again.
    } catch (e) {
      return e
    }
}
...

如何多次调用useQuery?

我可以随时调用吗?

我已经寻找了几个网站,但我找不到解决方案。

【问题讨论】:

    标签: javascript reactjs graphql react-hooks react-apollo


    【解决方案1】:

    来自阿波罗文档

    当 React 挂载并渲染一个调用 useQuery 钩子的组件时,Apollo Client 会自动执行指定的查询。但是,如果您想执行查询以响应不同的事件,例如用户单击按钮,该怎么办?

    useLazyQuery 钩子非常适合执行查询以响应 组件渲染以外的事件

    我建议useLazyQuery。简单来说,useQuery 将在您的组件渲染时运行,您可以使用skip 选项跳过初始运行。并且有一些方法可以随时重新获取/获取更多数据。或者你可以坚持useLazyQuery

    例如,如果您只想在用户点击按钮或滚动到底部时获取数据,那么您可以使用 useLazyQuery 钩子。

    【讨论】:

    • 根据帖子的标题,这个答案应该是公认的答案。让我点赞吧。
    • 不是真的它(useQuery)不能被停止......有一个“跳过”选项
    【解决方案2】:

    useQuery 是一个声明性的 React Hook。它并不意味着在经典函数的意义上被调用来接收数据。首先,确保了解 React Hooks 或者暂时不要使用它们(Stackoverflow 上 90% 的问题是因为人们试图一次学习太多东西)。 Apollo 文档非常适合官方的react-apollo 包,它使用了渲染道具。这同样有效,一旦您了解了 Apollo Client Hooks,您就可以进行一些重构。所以你的问题的答案:

    如何多次调用useQuery?

    您不会多次调用它。当查询结果可用或更新时,组件将自动重新呈现。

    我可以随时调用吗?

    不,只能在顶层调用钩子。相反,数据可以在您的函数中从上层范围(闭包)中获得。

    您的updateInformation 应该是一个更新应用程序缓存的突变,它再次触发 React 组件的重新呈现,因为它“订阅”了查询。在大多数情况下,更新是完全自动发生的,因为 Apollo 将通过 __typenameid 的组合来识别实体。下面是一些伪代码,说明了突变如何与突变一起工作:

    const GET_USER_LIST = gql`
      query GetUserList {
        users {
          id
          name
        }
      }
    `;
    
    const UPDATE_USER = gql`
      mutation UpdateUser($id: ID!, $name: String!) {
        updateUser(id: $id, update: { name: $name }) {
          success
          user {
            id
            name
          }
        }
      }
    `;
    
    const UserListComponen = (props) => {
      const { data, loading, error } = useQuery(GET_USER_LIST);
      const [updateUser] = useMutation(UPDATE_USER);
    
      const onSaveInformation = (id, name) => updateUser({ variables: { id, name });
    
      return (
        // ... use data.users and onSaveInformation in your JSX
      );
    }
    

    现在,如果用户的名称通过突变发生变化,Apollo 将自动更新缓存并触发组件的重新渲染。然后组件将自动显示新数据。欢迎使用 GraphQL 的强大功能!

    【讨论】:

    • 如果有人仍然没有得到完整的图片,这里有一个很好的例子。 ultimatecourses.com/blog/…
    • 感谢您的描述。我只是不明白如何呈现这个函数。渲染功能组件的唯一方法是通过它自己的状态或道具。但是当我执行 console.log(props) 时它是空的,但在返回时它仍然会在加载为 false 时重新渲染
    【解决方案3】:

    有回答提到应该如何使用 useQuery,还有使用 useLazyQuery 的建议。我认为关键的要点是了解 useQuery 与 useLazyQuery 的用例,您可以在文档中阅读这些用例。下面我试着从我的角度来解释一下。

    useQuery 是“声明性的”,就像 React 的其余部分一样,尤其是组件渲染。这意味着当 state 或 props 改变时,你应该期望每次渲染都会调用 useQuery。所以在英语中,就像“Hey React,当事情发生变化时,这就是what我希望你查询”。

    对于useLazyQuery,文档中的这一行是关键:“useLazyQuery 挂钩非常适合执行查询以响应组件渲染以外的事件”。用更一般的编程语言来说,它是“势在必行的”。这使您能够随心所欲地调用查询,无论是响应状态/属性更改(即使用 useEffect)还是按钮单击等事件处理程序。用英语来说,就像“Hey React,这就是我想要如何查询数据”。

    【讨论】:

      【解决方案4】:

      您可以使用 useQuery 返回的 fetchMore(),它主要用于分页。

      const { loading, client, fetchMore } = useQuery(GET_USER_LIST);
      const submit = async () => {
          // Perform save operation
      
          const userResp = await fetchMore({
            variables: {
                // Pass any args here
            },
            updateQuery(){
      
            }
          });
          console.log(userResp.data)
        };
      

      在此处阅读更多信息:fetchMore

      您也可以使用 useLazyQuery,但它会为您提供一个返回 void 的函数,并且数据会在您的函数外部返回。

      const [getUser, { loading, client, data }] = useLazyQuery(GET_USER_LIST);
      const submit = async () => {
          const userResp = await getUser({
            variables: {
              // Pass your args here
            },
            updateQuery() {},
          });
          console.log({ userResp }); // undefined
        };
      

      在此处阅读更多信息:useLazyQuery

      【讨论】:

        【解决方案5】:

        您可以创建一个可重用的 fetch 函数,如下所示:

        // Create query
        const query = `
            query GetUserList ($data: UserDataType){
                getUserList(data: $data){
                  uid,
                  first_name
                }
            }
        `;
        
        
        // Component
        export const TestComponent (props) {
        
          const onSaveInformation = async () => {
          
            // I want to call useQuery once again.  
            const getUsers = await fetchUserList();
          }
          
        
          // This is the reusable fetch function.
          const fetchUserList = async () => {
        
              // Update the URL to your Graphql Endpoint.
              return await fetch('http://localhost:8080/api/graphql?', {
              
                  method: 'POST',
                  headers: {
                      'Content-Type': 'application/json',
                      'Accept': 'application/json',
                  },
                  body: JSON.stringify({
                      query,
                      variables: { 
                         data: {
                            page: changePage,
                            pageSize: 10,
                          },
                      },
                  })
              }).then(
                    response => { return response.json(); }  
               ).catch(
                    error => console.log(error) // Handle the error response object
              );
          }
        
          return (
            <h1>Test Component</h1>
          );
          
        }

        【讨论】:

          【解决方案6】:

          请使用 const { loading, data, refetch } = useQuery(Query_Data) 并在需要时调用它,即 refetch()

          【讨论】:

          • refetch() 不刷新或重新加载,当参数与调用之前从现金而非服务器加载相同时重新获取
          猜你喜欢
          • 2020-10-30
          • 2019-10-06
          • 2020-01-02
          • 2019-09-14
          • 2020-08-13
          • 2020-01-23
          • 2020-03-24
          • 2021-03-02
          • 2020-04-13
          相关资源
          最近更新 更多