react-query中useQuery参数变更重请求与分页实现异常问题
问题根源
- React状态更新是异步批量执行的,在同一个useEffect执行栈中调用
setArrivals后,当前闭包内的arrivals变量还未完成更新,直接调用refetch必然拿到上一次的旧参数,你用的setTimeout 0方案本质是把请求推到状态更新完成后的宏任务队列执行,属于绕过问题的hack方案。 - 违背了React Query的核心设计逻辑:所有会影响查询结果的参数都应该放到queryKey数组中,React Query会自动监听queryKey的变化,自动触发重新请求,完全不需要手动调用refetch,也不需要额外的useEffect来同步参数。
- 存在冗余状态:
arrivals完全可以基于props.newArrivals和page状态计算得到,不需要单独用useState维护,多维护一份状态就多一份不同步的风险。
修正方案
完全可以删掉冗余的arrivals状态和不合理的useEffect逻辑,按照React Query的规范改写代码即可:
const HomePage = ({ newArrivals }) => { const [page, setPage] = useState(1); // 直接计算查询参数,不需要单独维护状态 const queryParams = useMemo(() => ({ ...newArrivals, page }), [newArrivals, page]); const newArrivalsQuery = useQuery( // 把影响查询的参数放到queryKey里,page变了会自动重新请求 ['productListByNewArrivals', page], () => getProductList(queryParams), { select: (data) => JSON.parse(data), keepPreviousData: true, // 加这个可以在加载下一页时保留上一页数据,提升分页体验 } ); return ( <> <NewArrivals newArrivalsQuery={newArrivalsQuery} page={page} setPage={setPage} /> </> ); }; // getServerSideProps逻辑不需要修改,预取的第一页数据会和客户端page=1的查询自动匹配复用
内容的提问来源于stack exchange,提问作者John John
相关产品推荐
相关产品推荐

