Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

105
Visualizações
React infinite scroll component - dataLength not working

I have a function newsFeed which is called by useEffect and makes a request to an endpoint to fetch all posts made by the logged in user as well as any users they follow, and then saves the data response to the state:

const [posts, setPosts] = useState([])
const [page, setPage] = useState(1)

useEffect(() => {
    newsFeed();
}, []

const newsFeed = async () => {
    await axios.post(
        `${process.env.REACT_APP_API}/news-feed/${page}`,
    )
    .then((res) => {
        setPosts(res.data);
        setPage(page + 1);
    })
    .catch((err) => {
        console.log(err);
    });
};

router.post('/news-feed/:page', newsFeed);

exports.newsFeed = async (req, res) => {
    try {
        const user = await User.findById(req.body.user._id);
        let following = user.following;
        following.push(req.body.user._id);

        const currentPage = req.params.page || 1;
        const perPage = 5;

        const posts = await Post.find({ postedBy: { $in: following } })
        .skip((currentPage - 1) * perPage)
        .sort({createdAt: -1})
        .limit(perPage);
        res.json(posts);
    } catch (err) {
        console.log(err);
    }
};

I want to use react-infinite-scroll-component to fetch only the first 20 posts on page load, then another 20 when user scrolls to the bottom etc.

I currently have this code to render the posts:

<div id='scrollableDiv' style={{ overflow: 'auto' }}>
    <InfiniteScroll
      dataLength={20}
      next={newsFeed}
      hasMore={true}
      loader={<FontAwesomeIcon icon={faSpinner} spin />}
      endMessage={
        <p style={{ textAlign: 'center' }}>
          <b>Yay! You have seen it all</b>
        </p>
      }
      scrollableTarget='scrollableDiv'
    >
        {posts.map((post) => (
        ...)}
    </InfiniteScroll>
</div>

What is now happening is that only the first 20 posts are rendered, with the loading spinner continuously displayed below.

I have tried adding page as a dependency to the useEffect callback and this does result in loading the posts in blocks of 20, however they are rendered automatically each second and overlap the previous block as if the app is literally changing the page and when all have been rendered an empty screen is displayed.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Your issue appears to be that your backend is returning all records every time you call it, since there are no parameters being passed on to it:

await axios.post(
    `${process.env.REACT_APP_API}/news-feed`,
)

This is not consistent with the documentation of the component which states:

The data is passed as children to the InfiniteScroll component and the data should contain previous items too. e.g. Initial data = [1, 2, 3] and then next load of data should be [1, 2, 3, 4, 5, 6].

So, you need to tell your backend which set of items to return, then append those items to the posts you already loaded in prior calls.

For instance, keep a reference of the page you need returned and call the backend with a parameter:

//In state declaration
const [pageNumber, setPageNumber] = useState(1);

//In loader function
await axios.post(
    `${process.env.REACT_APP_API}/news-feed/{pageNumber}`,
) 

Where pageNumber is a variable you keep in state with the current page number, then increment it every time you receive items. Something along the lines of:

await axios.post(
    `${process.env.REACT_APP_API}/news-feed/{pageNumber}`,
)
.then((res) => {
    let newPosts = posts;
    newPosts.concat(res.data);
    setPosts(newPosts);
    setPageNumber(pageNumber + 1);
})

If you are unable to modify the backend to support paging, then you will have to retrieve all records every time and slice them to select the ones you need to append. Not terribly difficult but very inefficient. Something like this:

//In state declaration
const [pageNumber, setPageNumber] = useState(0); //0 based

//In data loader
await axios.post(
    `${process.env.REACT_APP_API}/news-feed`,
)
.then((res) => {
    let newPosts = posts;
    let start = (pageNumber === 0) ? 0 : (pageNumber * 20) - 1;
    let addPosts = res.data.slice(start, 20);
    newPosts = newPosts.concat(addPosts);
    setPosts(newPosts);
    setPageNumber(pageNumber + 1);
})

I wrote this in a hurry so make sure to check for consistency and end of records. You get the idea. :-)

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda