Home > Enterprise >  Why do I need to click the Page number before I get the data first?
Why do I need to click the Page number before I get the data first?

Time:12-08

So I'm rendering filtered products, and now I want to create pagination. It is working but I need to click a page number first before it shows up. I already included a loading state, but it's not working properly.

My data is coming from the backend MongoDB

This is my first render: First Render

After Clicking page 1 enter image description here

const ProductList = ({products, category}) => {
  const [filteredProducts, setFilteredProducts]  = useState([])
  const [loading, setLoading] = useState(true)

  useEffect(() =>{
    const isAvailable = products.filter((product) => product.quantity !== 0 )
    setFilteredProducts(isAvailable)
    setLoading(false)
  },[setFilteredProducts, category,products])




  const firstIndex = 0
  const [pageSize, setPageSize] = useState(5)
  const [page, setPage] = useState(1)
  const [data,setData] = useState(filteredProducts.slice(firstIndex, pageSize))

  useEffect(() =>{
    setData(filteredProducts.slice(0, pageSize))
    setLoading(false)
  },[pageSize])


  const handleChange = (event, value) => {
    setPage(value);
    setData(filteredProducts.slice(firstIndex   pageSize * (value - 1), pageSize * value));
  };


  return (
    <>
    {loading ?
      <BeatLoader 
      color="#36d7b7" 
      loading={loading}
      size={50}
      aria-label="Loading Spinner"
      data-testid="loader"
      />
      :
      (
        <Box sx={{backgroundColor: '#f5f5f5', display:'flex', marginTop:2}}>
      <Container maxWidth="xl">
        <Typography sx={{textAlign: 'center', paddingY: '20px', fontWeight: 700, color: '#212121', typography: {xs: "h6", md: "h4"}}}>Products</Typography>
          <Box sx={{display: 'flex', alignItems:'center',justifyContent: 'space-evenly', flexWrap: 'wrap', gap: '10px'}}>
            {data.map((product) => (
              <ProductItem  key={product._id} product={product} />
              ))}
          </Box>
          <Pagination 
            sx={{display: 'flex', alignItems:'center',justifyContent:'center',margin: 4}}
            size="large"
            count={Math.ceil(filteredProducts.length/pageSize)}
            page={page}
            onChange={handleChange}
          />
      </Container>
    </Box>
    )
  }
  </>
  )
}

export default ProductList

CodePudding user response:

It looks like the second useEffect is using the value of filteredProducts but not having it in the dependencies array, so it could not update data when it is ready or if it changes.

This seems to be the reason data could only be updated with the handleChange event.

To fix this, try add filteredProducts to the dependencies array:

useEffect(() => {
  setData(filteredProducts.slice(0, pageSize));
  setLoading(false);
  //            
  • Related