英文:
Infinite Scroll with React useInfiniteQuery
问题
我对 react-query
还很生疏,遇到了一些在实现 useInfiniteQuery
函数时的问题。我尝试将其应用到我的网站上,但似乎并没有按预期递增 pageIndex
变量。pageIndex
一直保持在 0
,因此每次获取数据时都会导致重复的帖子。offset
变量用于从数据库中获取应获取查询的第 n
行数据。
寻求帮助,谢谢。
以下是前端部分的代码:
import React from "react";
import { useRef, useCallback} from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useInfiniteQuery } from "react-query";
const PAGE_LIMIT = 10;
const fetchPosts = async (key, pageIndex = 0) => {
const offset = pageIndex * PAGE_LIMIT;
try {
const { data } = await axios.get(`/posts`, {
params: { offset: offset, limit: PAGE_LIMIT },
});
return data;
} catch (err) {
console.log(err);
}
};
const Home = () => {
const {
fetchNextPage,
hasNextPage,
isFetchingNextPage,
data,
status,
error,
} = useInfiniteQuery("/posts", ({ pageIndex = 0 }) => fetchPosts(pageIndex), {
getNextPageParam: (lastPage, allPages) => {
return lastPage.length ? allPages.length : undefined;
},
});
const intObserver = useRef();
const lastPostRef = useCallback(
(post) => {
if (isFetchingNextPage) return;
if (intObserver.current) intObserver.current.disconnect();
intObserver.current = new IntersectionObserver((posts) => {
if (posts[0].isIntersecting && hasNextPage) {
console.log("We are near the last post!");
fetchNextPage();
}
});
if (post) intObserver.current.observe(post);
},
[isFetchingNextPage, fetchNextPage, hasNextPage]
);
if (status === "error")
return <p className="center">Error: {error.message}</p>;
const content = data?.pages.map((pg) => {
return pg.map((post, i) => {
if (pg.length === i + 1) {
return (
<Link ref={lastPostRef} className="link" to={`/post/${post.id}`}>
<div className="post" key={post.id}>
<p> {post.title}</p>
<p> {post.content}</p>
</div>
</Link>
);
}
return (
<Link className="link" to={`/post/${post.id}`}>
<div className="post" key={post.id}>
<p> {post.title}</p>
<p> {post.content}</p>
</div>
</Link>
);
});
});
return (
<div>
<div className="home">
<div className="container">
<div className="posts">
{content}
{isFetchingNextPage && (
<p className="center">Loading More Posts...</p>
)}
<p className="center">
<a href="#top">Back to Top</a>
</p>
</div>
</div>
</div>
</div>
);
};
export default Home;
以下是后端部分的代码:
import { db } from "../db.js";
export const getPosts = (req, res) => {
const { offset, limit } = req.query;
console.log(`Offset is ${offset}`);
const q = `SELECT * FROM test1 ORDER BY ID LIMIT ?, ?`;
db.query(q, [parseInt(offset), parseInt(limit)], (err, data) => {
if (err) return res.status(500).json(err);
return res.status(200).json(data);
});
};
英文:
I am new to react-query
and I am having some trouble implementing the useInfiniteQuery
function. I've tried implementing it into my website, however it doesn't seem to increment the pageIndex
variable as it should. The pageIndex
remains at 0
all the time, hence duplicating my posts every time I'm fetching the data. The offset
variable is used for my database to get the n
row from where the query is to be fetched.
Looking for help, thanks.
Here is the front-end part:
import React from "react";
import { useRef, useCallback} from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import { useInfiniteQuery } from "react-query";
const PAGE_LIMIT = 10;
const fetchPosts = async (key, pageIndex = 0) => {
const offset = pageIndex * PAGE_LIMIT;
try {
const { data } = await axios.get(`/posts`, {
params: { offset: offset, limit: PAGE_LIMIT },
});
return data;
} catch (err) {
console.log(err);
}
};
const Home = () => {
const {
fetchNextPage,
hasNextPage,
isFetchingNextPage,
data,
status,
error,
} = useInfiniteQuery("/posts", ({ pageIndex = 0 }) => fetchPosts(pageIndex), {
getNextPageParam: (lastPage, allPages) => {
return lastPage.length ? allPages.length : undefined;
},
});
const intObserver = useRef();
const lastPostRef = useCallback(
(post) => {
if (isFetchingNextPage) return;
if (intObserver.current) intObserver.current.disconnect();
intObserver.current = new IntersectionObserver((posts) => {
if (posts[0].isIntersecting && hasNextPage) {
console.log("We are near the last post!");
fetchNextPage();
}
});
if (post) intObserver.current.observe(post);
},
[isFetchingNextPage, fetchNextPage, hasNextPage]
);
if (status === "error")
return <p className="center">Error: {error.message}</p>;
const content = data?.pages.map((pg) => {
return pg.map((post, i) => {
if (pg.length === i + 1) {
return (
<Link ref={lastPostRef} className="link" to={`/post/${post.id}`}>
<div className="post" key={post.id}>
<p> {post.title}</p>
<p> {post.content}</p>
</div>
</Link>
);
}
return (
<Link className="link" to={`/post/${post.id}`}>
<div className="post" key={post.id}>
<p> {post.title}</p>
<p> {post.content}</p>
</div>
</Link>
);
});
});
return (
<div>
<div className="home">
<div className="container">
<div className="posts">
{content}
{isFetchingNextPage && (
<p className="center">Loading More Posts...</p>
)}
<p className="center">
<a href="#top">Back to Top</a>
</p>
</div>
</div>
</div>
</div>
);
};
export default Home;
Here is the back-end part:
import { db } from "../db.js";
export const getPosts = (req, res) => {
const { offset, limit } = req.query;
console.log(`Offset is ${offset}`);
const q = `SELECT * FROM test1 ORDER BY ID LIMIT ?, ?`;
db.query(q, [parseInt(offset), parseInt(limit)], (err, data) => {
if (err) return res.status(500).json(err);
return res.status(200).json(data);
});
};
答案1
得分: 1
fetch回调函数是您提供给useInfiniteQuery
的,它接收一个QueryFunctionContext
。它有一个名为pageParam
的属性。您使用了pageIndex
,但该属性不在该对象上。因为您为其提供了默认值为0
,所以它将始终为零。请改用pageParam
。
英文:
The fetch callback you give useInfiniteQuery
receives a QueryFunctionContext
. It has a property called pageParam
. You use pageIndex
which is not on that object. Because you give it a default value of 0
it will just always be zero. Use pageParam
instead.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论