在参数更改时使用 useQuery 重新获取
Re-fetching with useQuery on argument change
我正在尝试使用 react-query
实现分页。在页面更改时,我正在使用 setArrivals
更新 useEffect
内的页面。出于某种原因,我总是发送 arrivals
的先前值作为 getProductList
函数的参数。为了解决这个问题,我在 setTimeout
中发送了 refetch()
请求。它确实有效,但我觉得不合适。让我知道我做错了什么。
const HomePage = ({ newArrivals }) => {
const [page, setPage] = useState(1);
const [arrivals, setArrivals] = useState({ ...newArrivals, page: page });
useEffect(() => {
setArrivals((values) => {
console.log({ page });
return { ...values, page: page };
});
setTimeout(function () {
newArrivalsQuery.refetch();
}, 0);
}, [page]);
const newArrivalsQuery = useQuery(
['productListByNewArrivals'],
() => getProductList(arrivals),
{
select: useCallback((data) => {
return JSON.parse(data);
}, []),
}
);
return (
<>
<NewArrivals
newArrivalsQuery={newArrivalsQuery}
page={page}
setPage={setPage}
/>
</>
);
};
export async function getServerSideProps(context) {
const newArrivals = {
sort: 'createdAt',
order: 'desc',
};
try {
const queryClient = new QueryClient();
await queryClient.prefetchQuery('productListByNewArrivals', async () => {
const newArrivalsResult = await listProduct(newArrivals);
return JSON.stringify(newArrivalsResult);
});
return {
props: {
newArrivals: newArrivals,
dehydratedState: dehydrate(queryClient),
},
};
} catch (error) {
console.log('error: ', error);
if (error) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
}
}
最好的方法是将查询函数的依赖项添加到 queryKey。 react-query 是声明式的,如果 queryKey 发生变化,它将自动重新获取。如果您必须达到 useEffect
和 refetch
,这可能不是最简单的解决方案:
const HomePage = ({ newArrivals }) => {
const [page, setPage] = useState(1);
const [arrivals, setArrivals] = useState({ ...newArrivals, page: page });
const newArrivalsQuery = useQuery(
['productListByNewArrivals', arrivals],
() => getProductList(arrivals),
{
select: useCallback((data) => {
return JSON.parse(data);
}, []),
}
);
现在,arrivals
是 queryKey 的一部分,这就是您在 getProductList
的 queryFn 中使用的内容。现在您需要做的就是调用 setArrivals
并且 react-query 将重新获取。
旁注:看起来 arrivals
并不是真正的 state,而是 derived state。至少在这个片段中,你只调用了 setter 效果,这似乎是错误的。看起来你想与 page
保持同步并在每次调用 setPage
时计算它,所以你也可以这样做:
const [page, setPage] = useState(1);
const arrivals = { ...newArrivals, page: page };
我正在尝试使用 react-query
实现分页。在页面更改时,我正在使用 setArrivals
更新 useEffect
内的页面。出于某种原因,我总是发送 arrivals
的先前值作为 getProductList
函数的参数。为了解决这个问题,我在 setTimeout
中发送了 refetch()
请求。它确实有效,但我觉得不合适。让我知道我做错了什么。
const HomePage = ({ newArrivals }) => {
const [page, setPage] = useState(1);
const [arrivals, setArrivals] = useState({ ...newArrivals, page: page });
useEffect(() => {
setArrivals((values) => {
console.log({ page });
return { ...values, page: page };
});
setTimeout(function () {
newArrivalsQuery.refetch();
}, 0);
}, [page]);
const newArrivalsQuery = useQuery(
['productListByNewArrivals'],
() => getProductList(arrivals),
{
select: useCallback((data) => {
return JSON.parse(data);
}, []),
}
);
return (
<>
<NewArrivals
newArrivalsQuery={newArrivalsQuery}
page={page}
setPage={setPage}
/>
</>
);
};
export async function getServerSideProps(context) {
const newArrivals = {
sort: 'createdAt',
order: 'desc',
};
try {
const queryClient = new QueryClient();
await queryClient.prefetchQuery('productListByNewArrivals', async () => {
const newArrivalsResult = await listProduct(newArrivals);
return JSON.stringify(newArrivalsResult);
});
return {
props: {
newArrivals: newArrivals,
dehydratedState: dehydrate(queryClient),
},
};
} catch (error) {
console.log('error: ', error);
if (error) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
}
}
最好的方法是将查询函数的依赖项添加到 queryKey。 react-query 是声明式的,如果 queryKey 发生变化,它将自动重新获取。如果您必须达到 useEffect
和 refetch
,这可能不是最简单的解决方案:
const HomePage = ({ newArrivals }) => {
const [page, setPage] = useState(1);
const [arrivals, setArrivals] = useState({ ...newArrivals, page: page });
const newArrivalsQuery = useQuery(
['productListByNewArrivals', arrivals],
() => getProductList(arrivals),
{
select: useCallback((data) => {
return JSON.parse(data);
}, []),
}
);
现在,arrivals
是 queryKey 的一部分,这就是您在 getProductList
的 queryFn 中使用的内容。现在您需要做的就是调用 setArrivals
并且 react-query 将重新获取。
旁注:看起来 arrivals
并不是真正的 state,而是 derived state。至少在这个片段中,你只调用了 setter 效果,这似乎是错误的。看起来你想与 page
保持同步并在每次调用 setPage
时计算它,所以你也可以这样做:
const [page, setPage] = useState(1);
const arrivals = { ...newArrivals, page: page };