Skip to content

How can I create a hook that reacts to an event to load more data?

I am trying to create a functionality where if a user clicks on a LOAD MORE button, it returns more data.

I already have some code done but every time I click on the LOAD MORE button, it removes the first 12 items and sets the new 12 items, but I don’t want that, I want to keep the 12 old tems, It is just a regular load more functionality.

const Comp = ({ data }) => {
  const postsPerPage = 12
  const [postsToShow, setPostsToShow] = useState([])
  const [next, setNext] = useState(postsPerPage)
  let arrayForHoldingPosts = []
  const loopWithSlice = (start, end) => {
    const slicedPosts = data.products.slice(start, end)
    arrayForHoldingPosts = [...arrayForHoldingPosts, ...slicedPosts]
    setPostsToShow(arrayForHoldingPosts)
  }
  useEffect(() => {
    loopWithSlice(0, postsPerPage)
  }, [])
  const handleShowMorePosts = () => {
    loopWithSlice(next, next + postsPerPage)
    setNext(next + postsPerPage)
  }
  return (
    <div>
      {postsToShow.map(p => <div>...</div>)}
      <button onClick={handleShowMorePosts}>Load more</button>
    </div>
  )
}

Besides that, I need to turn this into a hook which I am going to using across the whole application.

What am I missing?

Any ideas?

Answer

You do not need an array arrayForHoldingPosts instead just use setPostsToShow( [...postsToShow, ...slicedPosts]);

arrayForHoldingPosts is becoming empty array after every renders so old data is lost.

Hook example

const useLoadMore = (data, postsPerPage = 2) => {
  const [postsToShow, setPostsToShow] = useState([]);
  const [next, setNext] = useState(postsPerPage);
  const loopWithSlice = (start, end) => {
    const slicedPosts = data.slice(start, end);
    setPostsToShow( [...postsToShow, ...slicedPosts]);
  };
  useEffect(() => {
    loopWithSlice(0, postsPerPage);
  }, []);
  const handleShowMorePosts = () => {
    loopWithSlice(next, next + postsPerPage);
    setNext(next + postsPerPage);
  };
  return { handleShowMorePosts, postsToShow }
}
const App = ({data}) => {
  const {handleShowMorePosts, postsToShow } = useLoadMore(data)
  return (
    <div>
      {postsToShow.map((p) => (
        <div>...</div>
      ))}
      <button onClick={handleShowMorePosts}>Load more</button>
    </div>
  );
};