Я пытаюсь реализовать отложенную загрузку в приложении стека MERN, как в producthunt .Я хочу, чтобы сообщения, созданные в текущую дату, отображались по умолчанию.Если пользователь прокрутит страницу вниз, он получит больше данных за предыдущую дату.Я использую реакцию бесконечного свитка.Тем не менее, похоже, что приложение запрашивает API как бесконечный цикл без прослушивания прокрутки.Я получил следующую ошибку.Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
Функция асинхронная / ожидание, поэтому я не понимаю, почему она продолжает вызывать новые запросы, даже если старый запрос еще не разрешен.
В компонентах Post
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);
Постредуктор
import {
GET_POSTS,
POST_ERROR,
UPDATE_LIKES,
UPDATE_LIKE,
UPDATE_COMMENT_LIKES,
DELETE_POST,
ADD_POST,
GET_POST,
ADD_COMMENT,
REMOVE_COMMENT,
ADD_SUB_COMMENT,
REMOVE_SUB_COMMENT,
UPDATE_STATUS
} from '../actions/types';
const initialState = {
posts: [],
post: null,
loading: true,
error: {}
};
export default function(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case GET_POSTS:
return {
...state,
posts: [...state.posts, ...payload],
// posts: payload,
loading: false
};
case GET_POST:
return {
...state,
post: payload,
loading: false
};
case ADD_POST:
return {
...state,
post: payload,
// posts: [payload, ...state.posts],
loading: false
};
case POST_ERROR:
return {
...state,
error: payload,
loading: false
};
case UPDATE_COMMENT_LIKES:
return {
...state,
post: {
...state.post,
comments: payload
},
loading: false
};
case UPDATE_LIKES:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id ? { ...post, likes: payload.likes } : post
),
loading: false
};
case UPDATE_LIKE:
return {
...state,
post: { ...state.post, likes: payload },
loading: false
};
case UPDATE_STATUS:
return {
...state,
posts: state.posts.map(post =>
post._id === payload.id ? { ...post, status: payload.status } : post
),
loading: false
};
case DELETE_POST:
return {
...state,
posts: state.posts.filter(post => post._id !== payload),
loading: false
};
case ADD_COMMENT:
return {
...state,
// payload is all the comments
post: { ...state.post, comments: payload },
loading: false
};
case ADD_SUB_COMMENT:
return {
...state,
// payload is all the comments of a post
post: { ...state.post, comments: payload },
loading: false
};
case REMOVE_COMMENT:
return {
...state,
post: {
...state.post,
comments: state.post.comments.filter(
comment => comment._id !== payload
),
loading: false
}
};
case REMOVE_SUB_COMMENT:
return {
...state,
post: {
...state.post,
comments: payload
// comments: state.post.comments.map(comment =>
// {
// if (comment._id === payload.commentId) {
// comment.subComments.filter(
// subcomment => subcomment._id === payload.subcommentId
// );
// }
// }
// )
},
loading: false
};
default:
return state;
}
}
Пост-действие
//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');
}
});