Reputation:
I wasn't sure how to title this correctly. I have an array of items, where I am mapping through them and creating a button for each item. when each button (which represents a category) is clicked, it loads the posts in that category. I am adding an extra item (which will also be a button) to the end of the array that will be a "view all" button, but it will call a different function. So far this component is like:
const Posts = ({ state }) => {
const [categories, setCategories] = useState([]);
const [categoryId, setCategoryId] = useState();
const [page, setPage] = useState(1);
const [posts, setPosts] = useState([]);
const [allPosts, setAllPosts] = useState([]);
useEffect(() => {
fetch(state.source.api + "/wp/v2/categories")
.then(response => response.json())
.then(data => {
setCategories(data);
})
}, []);
console.log(categories);
useEffect(() => {
if (categoryId) {
fetch(state.source.api + "/wp/v2/posts?categories=" + categoryId + "&per_page=5")
.then((response) => response.json())
.then((data) => {
setPosts(data);
});
}
}, [categoryId]);
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]);
const allCategories = categories.map((category, i) => (category))
allCategories.push("View All");
console.log(allCategories);
return (
<>
{allCategories.length > 0 ? (
allCategories.map((category, i) => {
return (
<>
<button className="btn" key={i} onClick={() => {
setPage(1);
setPosts([]);
setCategoryId(category.id);
}}>{category.name}</button>
{(category === "View All") && (<button>View all</button>)}
</>
)
})
) : (
<p>Loading...</p>
)
}
<div>
{posts.length === 0 ? (
<>
{allPosts.map((generalPost, i) => {
return (
<li key={i}>{generalPost.title.rendered}</li>
)
})}
<button onClick={() => { setPage(page + 1); }}>Load more</button>
</>
) : (
<>
<ol>
{posts.map((post, i) => {
// console.log(post.id);
return (
<li key={i}>{post.title.rendered}</li>
)
})}
</ol>
<button onClick={() => { setPage(page + 1); }}>Load more</button>
</>
)}
</div>
</>
)
}
I was able to get the "view all" button to be added to the end, but there seems to be an extra empty button before the "view all" button. I am not sure how that is getting in there. It's displaying like:
[Books] [Movies] [Songs] [ ] [View all]
Is there something wrong with the way I am adding the "view all" button to the array here?
Upvotes: 1
Views: 135
Reputation: 7080
In your original code, you are always rendering a <button class="btn">...</button>
+ conditional check to render <button>View all</button>
:
allCategories.map((category, i) => {
return (
<>
<button className="btn" key={i} onClick={() => {
setPage(1);
setPosts([]);
setCategoryId(category.id);
}}>{category.name}</button>
{(category === "View All") && (<button>View all</button>)}
</>
)
})
Therefore, when category === "View All"
is true, it also renders a <button class="btn">
element with empty content because in that case, category.name
is undefined.
What you need to do is to make a if-else statement or ternary expression to render only one of them:
allCategories.map((category, i) => {
return (
{(category === "View All") ? (
<button>View all</button>
) : (
<button className="btn" key={i} onClick={() => {
setPage(1);
setPosts([]);
setCategoryId(category.id);
}}>{category.name}</button>
)
)
})
Upvotes: 1