尝试使用 react-apollo-hooks 在函数中调用 useQuery

Trying call useQuery in function with react-apollo-hooks

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

可以随时调用吗?

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

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

How do I call useQuery multiple times?

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

Can I call it whenever I want?

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

您的 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 的强大功能!

来自阿波罗文档

When React mounts and renders a component that calls the useQuery hook, Apollo Client automatically executes the specified query. But what if you want to execute a query in response to a different event, such as a user clicking a button?

The useLazyQuery hook is perfect for executing queries in response to events other than component rendering

我建议 useLazyQuery. In simple terms, useQuery 将 运行 当你的组件被渲染时,你可以使用 skip 选项跳过初始的 运行。还有一些方法可以随时 refetch/fetch 更多数据。或者你可以坚持 useLazyQuery

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

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

useQuery "declarative" 很像 React 的其他部分,尤其是组件渲染。这意味着当状态或道具发生变化时,您应该期望在每次渲染时调用 useQuery。所以在英语中,就像 "Hey React, when things change, this is what I want you to query".

对于 useLazyQuery,文档中的这一行是关键:"The useLazyQuery hook is perfect for executing queries in response to events other than component rendering"。用更一般的编程语言来说,它是 "imperative"。这使您能够随心所欲地调用查询,无论它是响应 state/prop 更改(即使用 useEffect)还是按钮单击等事件处理程序。在英语中,就像 "Hey React, this is how I want to query for the data".

您可以使用从 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,但是它会给您一个 returns void 并且数据返回 outside[=24] 的函数=] 你的函数。

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

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

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

// 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>
  );
  
}

这是对我有用的替代方法:

const { refetch } = useQuery(GET_USER_LIST, {
    variables: {
      data: {
        page: changePage,
        pageSize: 10,
      },
    },
  }
);


const onSaveInformation = async () => {
    try {
      await updateInformation({...});
      const res = await refetch({ variables: { ... }});
      console.log(res);
    } catch (e) {
      return e;
    }
}

这里是针对类似问题的类似