Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

106
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda