user14249288
user14249288

Reputation:

Conditionally show button in React

I have a component that performs a pagination feature with blog posts. Each time the "load more" button is clicked, five more posts are loaded to the bottom of the page. I am drawing a blank right now on how to solve an issue with it though.

The Problem:

Once the "load more" button is clicked and all of the available posts are visible, the "load more" button should go away.

The Code:

const Posts = ({ state }) => {
  const [categories, setCategories] = useState([]);
  const [categoryId, setCategoryId] = useState();
  const [page, setPage] = useState(1);
  const [posts, setPosts] = useState([]); // Posts for each category
  const [allPosts, setAllPosts] = useState([]); // All posts from all categories

  // Get all of the available categories
  useEffect(() => {
    fetch(state.source.api + "/wp/v2/categories")
      .then(response => response.json())
      .then(data => {
        setCategories(data);
      })
  }, []);

  useEffect(() => {
    if (categoryId) {
      fetch(state.source.api + "/wp/v2/posts?categories=" + categoryId + "&per_page=5")
        .then((response) => response.json())
        .then((data) => {
          setPosts(data);
        });
    }
  }, [categoryId]);

  // Get posts for each category
  useEffect(() => {
    if (!categoryId) {
      return;
    }
    let url = state.source.api + "/wp/v2/posts?categories=" + categoryId + "&per_page=5";
    if (page > 1) {
      url += `&page=${page}`;
    }
    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        setPosts([...posts, ...data]);
      });
  }, [categoryId, page]);

  useEffect(() => {
    let url = state.source.api + "/wp/v2/posts?per_page=5";
    if (page > 1) {
      url += `&page=${page}`;
    }
    fetch(url)
      .then((response) => response.json())
      .then((data) => {
        setAllPosts([...allPosts, ...data]);
      });
  }, [page]);

  // Add View All button to category buttons array
  const allCategories = categories.map((category, i) => (category))
  allCategories.push("View All");

  return (
    <>
      {allCategories.map((category, i) => {
        return (
          (category === "View All") ? (
            <button onClick={() => { setPosts([]) }}>View All</button>
          ) : (
              <button className="btn" key={i} onClick={() => {
                setPage(1);
                setPosts([]);
                setCategoryId(category.id);
              }}>{category.name}</button>
            )
        )
      })}

      <div>
        {posts.length === 0 ? (
          <>
            {allPosts.map((allPost, i) => {
              return (
                <li key={i}>{allPost.title.rendered}</li>
              )
            })}
            <button onClick={() => { setPage(page + 1); }}>Load more</button>
          </>
        ) : (
            <>
              <ol>
                {posts.map((post, i) => {
                  return (
                    <li key={i}>{post.title.rendered}</li>
                  )
                })}
              </ol>

              <button onClick={() => { setPage(page + 1); }}>Load more</button>
            </>
          )}
      </div>
    </>
  )
}

Say there are a maximum of 3 pages worth of posts, five being viewed at a time - so 15 posts total... once all 3 pages are visible, and I click "load more" again (even though no more posts are available), I get a console error that ... my api... GET /wp/v2/posts?categories=78&per_page=5&page=4 400 (Bad Request), which obviously means that there was no page 4 to fetch because there are no more posts.

I think this requires an if statement, but I am not sure how I would get started writing it. Does anyone have any input?

Upvotes: 0

Views: 83

Answers (2)

Spencer Suraj
Spencer Suraj

Reputation: 11

Try an npm package called "react-paginate", with this you can easily implement the pagination logic without messing up with the code, and here is the link for this package https://www.npmjs.com/package/react-paginate Just go with the documentation and you can figure out how to do this, but if you face any problem then don't hesitate, just ask me.

Upvotes: 0

asmaa
asmaa

Reputation: 725

You should have a variable called totalPages, which hold the number of pages, and then compare between totalPages and page states, something like that:

{page <= totalPages && <button onClick={() => { setPage(page + 1); }}>Load more</button>}

in this case if page is 3 and totalPages is 4 the button will not display

Upvotes: 1

Related Questions