在带有react-apollo-hooks的函数中尝试调用useQuery

时间:2019-07-10 06:47:57

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

我想在需要时调用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?

我可以随时叫它吗?

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

6 个答案:

答案 0 :(得分:12)

来自阿波罗文档

当React挂载并呈现一个调用useQuery钩子的组件时,Apollo Client将自动执行指定的查询。但是,如果您想响应其他事件(例如用户单击按钮)来执行查询,该怎么办?

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

我建议使用useLazyQuery。简单来说,useQuery将在呈现组件时运行,无法停止它。但是有一些方法可以随时重新获取/获取更多数据。但是,如果您不想查询初始负载,则可以坚持使用useLazyQuery

例如,如果要在仅用户单击按钮或滚动到底部时获取数据,则可以使用useLazyQuery钩子。

答案 1 :(得分:2)

useQuery是声明性的React Hook。从经典的意义上讲,它并不是用来接收数据的。首先,请确保了解React Hooks或暂时不使用它们(Stackoverflow上90%的问题都发生了,因为人们试图一次学习很多东西)。 Apollo文档非常适合使用渲染道具的官方react-apollo软件包。这同样有效,一旦您了解了Apollo Client 挂钩,就可以进行一些重构。因此,您的问题的答案是:

  

如何多次调用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的强大功能!

答案 2 :(得分:2)

回答中提到应如何使用useQuery,以及有关使用useLazyQuery的建议。我认为关键要点在于了解useQuery和useLazyQuery的用例,您可以在文档中阅读这些用例。我将尝试从我的角度在下面进行解释。

useQuery是“声明性的”,与React的其余部分非常相似,尤其是组件渲染。这意味着您应该期望状态或道具发生变化时,每个渲染都将调用useQuery。所以用英语来说,就像,“嘿,React,当事情改变时,这是我要您查询的”。

对于useLazyQuery,文档中的这一行很关键:“ useLazyQuery挂钩非常适合响应组件渲染以外的事件来执行查询”。用更一般的编程语言来说,这是“当务之急”。无论是响应状态/属性更改(即使用useEffect)还是事件处理程序(例如按钮单击),这都使您能够按自己的意愿调用查询。用英语来说,就像“嘿,React,这是我要查询数据的方式”。

答案 3 :(得分:1)

您可以使用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 的函数,并且数据在您的函数的 outside 外返回。

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

答案 4 :(得分:0)

您可以创建一个可重复使用的 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>
  );
  
}

答案 5 :(得分:-2)

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