尝试使用 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?

我可以随时调用它吗?

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

来自阿波罗文档

当 React 挂载并渲染调用 useQuery 钩子的组件时,Apollo 客户端会自动执行指定的查询。但是,如果要执行查询以响应其他事件(例如用户单击按钮),该怎么办?

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

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

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

useQuery是一个声明性的 React Hook。它并不意味着在接收数据的经典函数的意义上被调用。首先,确保理解 React Hooks,或者干脆暂时不使用它们(Stackoverflow 上 90% 的问题都是因为人们试图一次学习太多东西)。Apollo 文档非常适合使用渲染道具的官方react-apollo包。这同样有效,一旦你理解了 Apollo 客户端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 的强大功能!

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

useQuery 是"声明式"的,就像 React 的其余部分一样,尤其是组件渲染。这意味着您应该期望在状态或 props 更改时调用每个渲染的 useQuery。所以在英语中,它就像,"嘿反应,当事情发生变化时,这就是我希望你查询的内容"。

对于useLazyQuery,文档中的这一行是关键:"useLazyQuery钩子非常适合执行查询以响应组件渲染以外的事件"。用更一般的编程术语来说,它是"命令式的"。这使您能够根据需要调用查询,无论是响应状态/属性更改(即使用 useEffect)还是按钮单击等事件处理程序。在英语中,就像是"嘿反应,这就是我想查询数据的方式"。

您可以使用从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)
};

在此处阅读更多: 获取更多

你也可以使用 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

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

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

对于一个类似的问题,这里有一个类似的答案。

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

最新更新