无限滚动使用React的useInfiniteQuery

huangapple go评论100阅读模式
英文:

Infinite Scroll with React useInfiniteQuery

问题

我对 react-query 还很生疏,遇到了一些在实现 useInfiniteQuery 函数时的问题。我尝试将其应用到我的网站上,但似乎并没有按预期递增 pageIndex 变量。pageIndex 一直保持在 0,因此每次获取数据时都会导致重复的帖子。offset 变量用于从数据库中获取应获取查询的第 n 行数据。

寻求帮助,谢谢。

以下是前端部分的代码:

  1. import React from "react";
  2. import { useRef, useCallback} from "react";
  3. import axios from "axios";
  4. import { Link } from "react-router-dom";
  5. import { useInfiniteQuery } from "react-query";
  6. const PAGE_LIMIT = 10;
  7. const fetchPosts = async (key, pageIndex = 0) => {
  8. const offset = pageIndex * PAGE_LIMIT;
  9. try {
  10. const { data } = await axios.get(`/posts`, {
  11. params: { offset: offset, limit: PAGE_LIMIT },
  12. });
  13. return data;
  14. } catch (err) {
  15. console.log(err);
  16. }
  17. };
  18. const Home = () => {
  19. const {
  20. fetchNextPage,
  21. hasNextPage,
  22. isFetchingNextPage,
  23. data,
  24. status,
  25. error,
  26. } = useInfiniteQuery("/posts", ({ pageIndex = 0 }) => fetchPosts(pageIndex), {
  27. getNextPageParam: (lastPage, allPages) => {
  28. return lastPage.length ? allPages.length : undefined;
  29. },
  30. });
  31. const intObserver = useRef();
  32. const lastPostRef = useCallback(
  33. (post) => {
  34. if (isFetchingNextPage) return;
  35. if (intObserver.current) intObserver.current.disconnect();
  36. intObserver.current = new IntersectionObserver((posts) => {
  37. if (posts[0].isIntersecting && hasNextPage) {
  38. console.log("We are near the last post!");
  39. fetchNextPage();
  40. }
  41. });
  42. if (post) intObserver.current.observe(post);
  43. },
  44. [isFetchingNextPage, fetchNextPage, hasNextPage]
  45. );
  46. if (status === "error")
  47. return <p className="center">Error: {error.message}</p>;
  48. const content = data?.pages.map((pg) => {
  49. return pg.map((post, i) => {
  50. if (pg.length === i + 1) {
  51. return (
  52. <Link ref={lastPostRef} className="link" to={`/post/${post.id}`}>
  53. <div className="post" key={post.id}>
  54. <p> {post.title}</p>
  55. <p> {post.content}</p>
  56. </div>
  57. </Link>
  58. );
  59. }
  60. return (
  61. <Link className="link" to={`/post/${post.id}`}>
  62. <div className="post" key={post.id}>
  63. <p> {post.title}</p>
  64. <p> {post.content}</p>
  65. </div>
  66. </Link>
  67. );
  68. });
  69. });
  70. return (
  71. <div>
  72. <div className="home">
  73. <div className="container">
  74. <div className="posts">
  75. {content}
  76. {isFetchingNextPage && (
  77. <p className="center">Loading More Posts...</p>
  78. )}
  79. <p className="center">
  80. <a href="#top">Back to Top</a>
  81. </p>
  82. </div>
  83. </div>
  84. </div>
  85. </div>
  86. );
  87. };
  88. export default Home;

以下是后端部分的代码:

  1. import { db } from "../db.js";
  2. export const getPosts = (req, res) => {
  3. const { offset, limit } = req.query;
  4. console.log(`Offset is ${offset}`);
  5. const q = `SELECT * FROM test1 ORDER BY ID LIMIT ?, ?`;
  6. db.query(q, [parseInt(offset), parseInt(limit)], (err, data) => {
  7. if (err) return res.status(500).json(err);
  8. return res.status(200).json(data);
  9. });
  10. };
英文:

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:

  1. import React from &quot;react&quot;;
  2. import { useRef, useCallback} from &quot;react&quot;;
  3. import axios from &quot;axios&quot;;
  4. import { Link } from &quot;react-router-dom&quot;;
  5. import { useInfiniteQuery } from &quot;react-query&quot;;
  6. const PAGE_LIMIT = 10;
  7. const fetchPosts = async (key, pageIndex = 0) =&gt; {
  8. const offset = pageIndex * PAGE_LIMIT;
  9. try {
  10. const { data } = await axios.get(`/posts`, {
  11. params: { offset: offset, limit: PAGE_LIMIT },
  12. });
  13. return data;
  14. } catch (err) {
  15. console.log(err);
  16. }
  17. };
  18. const Home = () =&gt; {
  19. const {
  20. fetchNextPage,
  21. hasNextPage,
  22. isFetchingNextPage,
  23. data,
  24. status,
  25. error,
  26. } = useInfiniteQuery(&quot;/posts&quot;, ({ pageIndex = 0 }) =&gt; fetchPosts(pageIndex), {
  27. getNextPageParam: (lastPage, allPages) =&gt; {
  28. return lastPage.length ? allPages.length : undefined;
  29. },
  30. });
  31. const intObserver = useRef();
  32. const lastPostRef = useCallback(
  33. (post) =&gt; {
  34. if (isFetchingNextPage) return;
  35. if (intObserver.current) intObserver.current.disconnect();
  36. intObserver.current = new IntersectionObserver((posts) =&gt; {
  37. if (posts[0].isIntersecting &amp;&amp; hasNextPage) {
  38. console.log(&quot;We are near the last post!&quot;);
  39. fetchNextPage();
  40. }
  41. });
  42. if (post) intObserver.current.observe(post);
  43. },
  44. [isFetchingNextPage, fetchNextPage, hasNextPage]
  45. );
  46. if (status === &quot;error&quot;)
  47. return &lt;p className=&quot;center&quot;&gt;Error: {error.message}&lt;/p&gt;;
  48. const content = data?.pages.map((pg) =&gt; {
  49. return pg.map((post, i) =&gt; {
  50. if (pg.length === i + 1) {
  51. return (
  52. &lt;Link ref={lastPostRef} className=&quot;link&quot; to={`/post/${post.id}`}&gt;
  53. &lt;div className=&quot;post&quot; key={post.id}&gt;
  54. &lt;p&gt; {post.title}&lt;/p&gt;
  55. &lt;p&gt; {post.content}&lt;/p&gt;
  56. &lt;/div&gt;
  57. &lt;/Link&gt;
  58. );
  59. }
  60. return (
  61. &lt;Link className=&quot;link&quot; to={`/post/${post.id}`}&gt;
  62. &lt;div className=&quot;post&quot; key={post.id}&gt;
  63. &lt;p&gt; {post.title}&lt;/p&gt;
  64. &lt;p&gt; {post.content}&lt;/p&gt;
  65. &lt;/div&gt;
  66. &lt;/Link&gt;
  67. );
  68. });
  69. });
  70. return (
  71. &lt;div&gt;
  72. &lt;div className=&quot;home&quot;&gt;
  73. &lt;div className=&quot;container&quot;&gt;
  74. &lt;div className=&quot;posts&quot;&gt;
  75. {content}
  76. {isFetchingNextPage &amp;&amp; (
  77. &lt;p className=&quot;center&quot;&gt;Loading More Posts...&lt;/p&gt;
  78. )}
  79. &lt;p className=&quot;center&quot;&gt;
  80. &lt;a href=&quot;#top&quot;&gt;Back to Top&lt;/a&gt;
  81. &lt;/p&gt;
  82. &lt;/div&gt;
  83. &lt;/div&gt;
  84. &lt;/div&gt;
  85. &lt;/div&gt;
  86. );
  87. };
  88. export default Home;

Here is the back-end part:

  1. import { db } from &quot;../db.js&quot;;
  2. export const getPosts = (req, res) =&gt; {
  3. const { offset, limit } = req.query;
  4. console.log(`Offset is ${offset}`);
  5. const q = `SELECT * FROM test1 ORDER BY ID LIMIT ?, ?`;
  6. db.query(q, [parseInt(offset), parseInt(limit)], (err, data) =&gt; {
  7. if (err) return res.status(500).json(err);
  8. return res.status(200).json(data);
  9. });
  10. };

答案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.

huangapple
  • 本文由 发表于 2023年2月14日 20:35:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75447918.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定