Javascript 在无限滚动中超过最大更新深度
我正在尝试在MERN stack应用程序中实现延迟加载,如中所示。我希望默认显示在当前日期创建的帖子。如果用户向下滚动,它将在上一个日期获取更多数据。我用的是无限卷轴。然而,似乎应用程序对api的请求就像一个无限循环,而不监听滚动。我犯了以下错误。 超出了最大更新深度。当组件在componentWillUpdate或componentDidUpdate内重复调用setState时,可能会发生这种情况。React限制嵌套更新的数量以防止无限循环。 这个函数是async/await,所以我不明白为什么它一直在调用新的请求,即使旧的请求还没有被解析 在一个Post组件中Javascript 在无限滚动中超过最大更新深度,javascript,node.js,reactjs,infinite-scroll,Javascript,Node.js,Reactjs,Infinite Scroll,我正在尝试在MERN stack应用程序中实现延迟加载,如中所示。我希望默认显示在当前日期创建的帖子。如果用户向下滚动,它将在上一个日期获取更多数据。我用的是无限卷轴。然而,似乎应用程序对api的请求就像一个无限循环,而不监听滚动。我犯了以下错误。 超出了最大更新深度。当组件在componentWillUpdate或componentDidUpdate内重复调用setState时,可能会发生这种情况。React限制嵌套更新的数量以防止无限循环。 这个函数是async/await,所以我不明白为什
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Spinner from '../layout/Spinner';
import PostItem from './PostItem';
import UserItem from '../users/UserItem';
import TopDiscussion from '../TopDiscussion';
import SmallAbout from '../SmallAbout';
import { getPostsByDate } from '../../actions/post';
import Moment from 'react-moment';
import InfiniteScroll from 'react-infinite-scroller';
const Posts = ({ getPostsByDate, post: { posts, loading } }) => {
const now = new Date();
const startOfToday = new Date(
now.getFullYear(),
now.getMonth(),
now.getDate()
);
// startOfToday = startOfToday -1
useEffect(() => {
getPostsByDate(startOfToday);
}, [getPostsByDate]);
const [date, setDate] = useState(startOfToday);
const [shown, setShown] = useState();
const getPosts = () => {
getPostsByDate(date);
let count = new Date(date);
count.setDate(count.getDate() - 1);
setDate(count);
};
return loading ? (
<Spinner />
) : (
<div className='main-grid'>
<div className='posts-grid'>
<h1 className='large text-primary'>Ideas</h1>
<div className='posts'>
<div className='post-dummy'>
<InfiniteScroll
dataLength={posts.length}
pageStart={0}
loadMore={getPosts}
hasMore={posts && posts.length < 10}
loader={
<div className='loader' key={0}>
Loading ...
</div>
}
>
{posts
.sort((a, b) =>
a.likes.length > b.likes.length
? -1
: b.likes.length > a.likes.length
? 1
: 0
)
.map(post => (
<PostItem key={post._id} post={post} />
))}
</InfiniteScroll>
</div>
</div>
</div>
<div className='right-panel-grid'>
<SmallAbout />
<UserItem />
<TopDiscussion posts={posts} />
<div
className='fb-group'
data-href='https://www.facebook.com/groups/ideatoshare/'
data-width='350'
data-show-social-context='true'
data-show-metadata='false'
></div>
<iframe
title='producthunt'
style={{ border: 'none' }}
src='https://cards.producthunt.com/cards/posts/168618?v=1'
width='350'
height='405'
frameBorder='0'
scrolling='no'
allowFullScreen
></iframe>
</div>
</div>
);
};
Posts.propTypes = {
getPostsByDate: PropTypes.func.isRequired,
post: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
post: state.post
});
export default connect(
mapStateToProps,
{ getPostsByDate }
)(Posts);
事后行动
//GetTodayPost
export const getPostsByDate = date => async dispatch => {
try {
const res = await axios.get(`/api/posts/${date}`);
dispatch({
type: GET_POSTS,
payload: res.data
});
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { msg: err.response.statusText, status: err.response.status }
});
}
};
后API
router.get('/:date', async (req, res) => {
try {
const startOfToday = new Date(req.params.date);
const endOfToday = new Date(req.params.date);
endOfToday.setDate(endOfToday.getDate() + 1);
const posts = await Post.find({
date: { $gte: startOfToday, $lte: endOfToday }
}).sort({
date: -1
});
res.json(posts);
} catch (err) {
console.error(err.message);
res.send(500).send('Server Error');
}
});
编辑:我已用..更新了您的回购协议。。你的问题是,你的API并不像你声称的那样是“无限制的”,你实际上需要检查是否所有帖子都已加载。。使用我提供的示例以及我对您的回购协议所做的更新,您应该能够从这里了解情况 好的。。因此,在使用
InfiniteScroll
进行一些测试之后,这似乎发生了,因为您的hasMore
属性始终等于true
。。。您必须指定某种类型的条件,以便InfiniteScroll
知道何时加载更多数据,何时不加载更多数据
在添加检查之前,我遇到了与您相同的错误,它告诉InfiniteSroll
没有更多的数据要加载
我构建了以下示例来演示如何使用InfiniteScroll
PostsContainer.js
import React, { useState, useEffect } from "react";
import Posts from "./Posts";
import InfiniteScroll from "react-infinite-scroller";
const loadingStyle = {
textAlign: "center",
fontSize: "48px",
color: "red"
};
function PostsContainer({ url, itemsToDisplay = 5 }) {
const [data, setData] = useState();
const [shownData, setShownData] = useState();
useEffect(() => {
(async () => {
let items = await fetchPosts(url);
let itemsToShow = selectNItems(items, itemsToDisplay);
setShownData(itemsToShow);
setData(items);
})();
}, [url]);
async function fetchPosts(url) {
let res = await fetch(url);
return await res.json();
}
const selectNItems = (obj, n) => {
return obj.slice(0, n);
}
const loadMorePosts = () => {
let items =
data &&
shownData &&
selectNItems(data, shownData.length + itemsToDisplay)
setShownData(items);
};
return (
<InfiniteScroll
pageStart={0}
loadMore={loadMorePosts}
hasMore={data && shownData && data.length > shownData.length}
loader={<div style={loadingStyle}>Loading ...</div>}
useWindow={true}
>
<Posts posts={shownData} />
</InfiniteScroll>
);
}
export default PostsContainer;
import React from 'react';
import Post from './Post';
const headingStyle = {
textAlign: 'center',
}
function Posts({ posts }) {
return(
<div>
<h1 style={headingStyle}>Posts</h1>
{posts && posts.length > 0 && posts.map((p, i) => <Post key={i} data={p} index={i} />)}
</div>
);
}
export default Posts;
import React from "react";
const containerStyle = {
border: "1px solid black",
margin: "10px auto",
maxWidth: "50vw",
padding: '0px 10px 0px 0px'
};
const postHeaderStyle = {
textAlign: "center",
padding: "0px"
};
function Post({ data, index }) {
return (
<div style={containerStyle}>
{index !== "" && <h3 style={postHeaderStyle}>Post #{index}</h3>}
<ul>
<li>
<b>userId:</b> {data.userId}
</li>
<li>
<b>id:</b> {data.id}
</li>
<li>
<b>title:</b> {data.title}
</li>
<li>
<b>body:</b> {data.body}
</li>
</ul>
</div>
);
}
export default Post;
import React from "react";
import { render } from "react-dom";
import PostsContainer from "./Components/PostsContainer";
function App() {
return (
<PostsContainer
itemsToDisplay={5}
url="https://jsonplaceholder.typicode.com/posts"
/>
);
}
render(<App />, document.getElementById("root"));
import React,{useState,useffect}来自“React”;
从“/Posts”导入帖子;
从“反应无限滚动条”导入无限滚动条;
常量加载方式={
textAlign:“居中”,
字体大小:“48px”,
颜色:“红色”
};
函数PostsContainer({url,itemsToDisplay=5}){
const[data,setData]=useState();
const[shownData,setShownData]=useState();
useffect(()=>{
(异步()=>{
let items=等待获取帖子(url);
let itemsToShow=选择项(items,itemsToDisplay);
设置显示数据(项目显示);
设置数据(项目);
})();
},[url]);
异步函数fetchPosts(url){
let res=等待获取(url);
return wait res.json();
}
const selectNItems=(对象,n)=>{
返回对象切片(0,n);
}
const loadMorePosts=()=>{
让项目=
资料&&
shownada&
选择项目(数据,显示数据长度+项目显示)
设置显示数据(项目);
};
返回(
shownData.length}
加载器={正在加载…}
useWindow={true}
>
);
}
导出默认PostsContainer;
Posts.js
import React, { useState, useEffect } from "react";
import Posts from "./Posts";
import InfiniteScroll from "react-infinite-scroller";
const loadingStyle = {
textAlign: "center",
fontSize: "48px",
color: "red"
};
function PostsContainer({ url, itemsToDisplay = 5 }) {
const [data, setData] = useState();
const [shownData, setShownData] = useState();
useEffect(() => {
(async () => {
let items = await fetchPosts(url);
let itemsToShow = selectNItems(items, itemsToDisplay);
setShownData(itemsToShow);
setData(items);
})();
}, [url]);
async function fetchPosts(url) {
let res = await fetch(url);
return await res.json();
}
const selectNItems = (obj, n) => {
return obj.slice(0, n);
}
const loadMorePosts = () => {
let items =
data &&
shownData &&
selectNItems(data, shownData.length + itemsToDisplay)
setShownData(items);
};
return (
<InfiniteScroll
pageStart={0}
loadMore={loadMorePosts}
hasMore={data && shownData && data.length > shownData.length}
loader={<div style={loadingStyle}>Loading ...</div>}
useWindow={true}
>
<Posts posts={shownData} />
</InfiniteScroll>
);
}
export default PostsContainer;
import React from 'react';
import Post from './Post';
const headingStyle = {
textAlign: 'center',
}
function Posts({ posts }) {
return(
<div>
<h1 style={headingStyle}>Posts</h1>
{posts && posts.length > 0 && posts.map((p, i) => <Post key={i} data={p} index={i} />)}
</div>
);
}
export default Posts;
import React from "react";
const containerStyle = {
border: "1px solid black",
margin: "10px auto",
maxWidth: "50vw",
padding: '0px 10px 0px 0px'
};
const postHeaderStyle = {
textAlign: "center",
padding: "0px"
};
function Post({ data, index }) {
return (
<div style={containerStyle}>
{index !== "" && <h3 style={postHeaderStyle}>Post #{index}</h3>}
<ul>
<li>
<b>userId:</b> {data.userId}
</li>
<li>
<b>id:</b> {data.id}
</li>
<li>
<b>title:</b> {data.title}
</li>
<li>
<b>body:</b> {data.body}
</li>
</ul>
</div>
);
}
export default Post;
import React from "react";
import { render } from "react-dom";
import PostsContainer from "./Components/PostsContainer";
function App() {
return (
<PostsContainer
itemsToDisplay={5}
url="https://jsonplaceholder.typicode.com/posts"
/>
);
}
render(<App />, document.getElementById("root"));
从“React”导入React;
从“./Post”导入Post;
常数头样式={
textAlign:'中心',
}
职能职位({Posts}){
返回(
帖子
{posts&&posts.length>0&&posts.map((p,i)=>)}
);
}
导出默认职位;
Post.js
import React, { useState, useEffect } from "react";
import Posts from "./Posts";
import InfiniteScroll from "react-infinite-scroller";
const loadingStyle = {
textAlign: "center",
fontSize: "48px",
color: "red"
};
function PostsContainer({ url, itemsToDisplay = 5 }) {
const [data, setData] = useState();
const [shownData, setShownData] = useState();
useEffect(() => {
(async () => {
let items = await fetchPosts(url);
let itemsToShow = selectNItems(items, itemsToDisplay);
setShownData(itemsToShow);
setData(items);
})();
}, [url]);
async function fetchPosts(url) {
let res = await fetch(url);
return await res.json();
}
const selectNItems = (obj, n) => {
return obj.slice(0, n);
}
const loadMorePosts = () => {
let items =
data &&
shownData &&
selectNItems(data, shownData.length + itemsToDisplay)
setShownData(items);
};
return (
<InfiniteScroll
pageStart={0}
loadMore={loadMorePosts}
hasMore={data && shownData && data.length > shownData.length}
loader={<div style={loadingStyle}>Loading ...</div>}
useWindow={true}
>
<Posts posts={shownData} />
</InfiniteScroll>
);
}
export default PostsContainer;
import React from 'react';
import Post from './Post';
const headingStyle = {
textAlign: 'center',
}
function Posts({ posts }) {
return(
<div>
<h1 style={headingStyle}>Posts</h1>
{posts && posts.length > 0 && posts.map((p, i) => <Post key={i} data={p} index={i} />)}
</div>
);
}
export default Posts;
import React from "react";
const containerStyle = {
border: "1px solid black",
margin: "10px auto",
maxWidth: "50vw",
padding: '0px 10px 0px 0px'
};
const postHeaderStyle = {
textAlign: "center",
padding: "0px"
};
function Post({ data, index }) {
return (
<div style={containerStyle}>
{index !== "" && <h3 style={postHeaderStyle}>Post #{index}</h3>}
<ul>
<li>
<b>userId:</b> {data.userId}
</li>
<li>
<b>id:</b> {data.id}
</li>
<li>
<b>title:</b> {data.title}
</li>
<li>
<b>body:</b> {data.body}
</li>
</ul>
</div>
);
}
export default Post;
import React from "react";
import { render } from "react-dom";
import PostsContainer from "./Components/PostsContainer";
function App() {
return (
<PostsContainer
itemsToDisplay={5}
url="https://jsonplaceholder.typicode.com/posts"
/>
);
}
render(<App />, document.getElementById("root"));
从“React”导入React;
常量集装箱样式={
边框:“1px纯黑”,
边距:“10px自动”,
最大宽度:“50vw”,
填充:“0px 10px 0px 0px”
};
const postHeaderStyle={
textAlign:“居中”,
填充:“0px”
};
函数Post({data,index}){
返回(
{index!=''&&Post{index}
-
userId:{data.userId}
-
id:{data.id}
-
标题:{data.title}
-
正文:{data.body}
);
}
导出默认帖子;
index.js
import React, { useState, useEffect } from "react";
import Posts from "./Posts";
import InfiniteScroll from "react-infinite-scroller";
const loadingStyle = {
textAlign: "center",
fontSize: "48px",
color: "red"
};
function PostsContainer({ url, itemsToDisplay = 5 }) {
const [data, setData] = useState();
const [shownData, setShownData] = useState();
useEffect(() => {
(async () => {
let items = await fetchPosts(url);
let itemsToShow = selectNItems(items, itemsToDisplay);
setShownData(itemsToShow);
setData(items);
})();
}, [url]);
async function fetchPosts(url) {
let res = await fetch(url);
return await res.json();
}
const selectNItems = (obj, n) => {
return obj.slice(0, n);
}
const loadMorePosts = () => {
let items =
data &&
shownData &&
selectNItems(data, shownData.length + itemsToDisplay)
setShownData(items);
};
return (
<InfiniteScroll
pageStart={0}
loadMore={loadMorePosts}
hasMore={data && shownData && data.length > shownData.length}
loader={<div style={loadingStyle}>Loading ...</div>}
useWindow={true}
>
<Posts posts={shownData} />
</InfiniteScroll>
);
}
export default PostsContainer;
import React from 'react';
import Post from './Post';
const headingStyle = {
textAlign: 'center',
}
function Posts({ posts }) {
return(
<div>
<h1 style={headingStyle}>Posts</h1>
{posts && posts.length > 0 && posts.map((p, i) => <Post key={i} data={p} index={i} />)}
</div>
);
}
export default Posts;
import React from "react";
const containerStyle = {
border: "1px solid black",
margin: "10px auto",
maxWidth: "50vw",
padding: '0px 10px 0px 0px'
};
const postHeaderStyle = {
textAlign: "center",
padding: "0px"
};
function Post({ data, index }) {
return (
<div style={containerStyle}>
{index !== "" && <h3 style={postHeaderStyle}>Post #{index}</h3>}
<ul>
<li>
<b>userId:</b> {data.userId}
</li>
<li>
<b>id:</b> {data.id}
</li>
<li>
<b>title:</b> {data.title}
</li>
<li>
<b>body:</b> {data.body}
</li>
</ul>
</div>
);
}
export default Post;
import React from "react";
import { render } from "react-dom";
import PostsContainer from "./Components/PostsContainer";
function App() {
return (
<PostsContainer
itemsToDisplay={5}
url="https://jsonplaceholder.typicode.com/posts"
/>
);
}
render(<App />, document.getElementById("root"));
从“React”导入React;
从“react dom”导入{render};
从“/Components/PostsContainer”导入PostsContainer;
函数App(){
返回(
);
}
render(,document.getElementById(“根”));
您是在为InfiniteScroll元素使用npm包,还是自定义的?无论哪种方式,如何实现loadMore
?您使用的是哪个InfiniteScroll软件包?我猜这是因为您在getPosts
中调用getPostByDate
,并且getPostByDate
被列为useffect
的依赖项数组。。如果将useffect
中的[getPostByDate]
更改为just[]
是否仍会发生这种情况?对于那些想知道正在使用的软件包的人,您将不得不分享更多的代码和redux设置,以供任何人帮助。你能用整个Posts
组件和一些redux代码更新你的帖子吗?听起来这个问题与您没有跟踪当前显示的项目数量与项目总数有关。如果您查看上面我的PostsContainer
组件,它显示了您必须如何跟踪总项目以及显示的项目…我想这一切都取决于您是否知道您使用的API是否有限制。。例如,我知道我使用的API只有100篇文章。。我更新了StackBlitz演示,展示了如何使用Redux实现这一点,以及如何在loadMore
期间调用API。。我即将崩溃,但明天我将用一些Redux代码和StackBlitz更新的组件更新我的答案。。显然,您希望PostsContainer更灵活一些,但我只是想向您展示一下目前如何实现这一点。您使用的是什么API?它是公开的吗?我在任何地方都没有看到它。哦,好吧,祝你好运把这个修好!