If I understand correctly, you are looking for a means to structure your data from your end point and then create a UI where users can show/hide content based on a tag or category.
Below is an example of some data and UI that can function as a model for what you are looking for. You will likely need to structure your data in a similar format to take advantage of the ways the current functions store data and respond to user input. If you have control of your endpoint, you can restructure the data accordingly. Alternatively if you don't control the endpoint, you can create a function that structures it as needed. Lastly, you can always adapt this model to suit your data as needed.
CodeSandbox: https://codesandbox.io/s/stack-63862326-library-t1xx7
import React, { useState } from "react";
import styled from "styled-components";
// here is some example data that you should strive to construct if
// you happen to have control over your endpoint; otherwise you can
// reconstruct your data in a way that looks closer to this format
const exampleAPIDat = [
{
name: "Harry Potter",
category: "fantasy",
thumbnail:
"https://images-na.ssl-images-amazon.com/images/I/81YOuOGFCJL.jpg"
},
{
name: "Gardens of the Moon",
category: "fantasy",
thumbnail:
"https://vignette.wikia.nocookie.net/malazan/images/6/67/GoTM_UK_AR.jpg/revision/latest?cb=20080327022138"
},
{
name: "Use of Weapons",
category: "Sci-Fi",
thumbnail: "https://m.media-amazon.com/images/I/51NfClNMlhL.jpg"
},
{
name: "Dune",
category: "Sci-Fi",
thumbnail: "https://m.media-amazon.com/images/I/41UZeCEKOBL.jpg"
}
];
export default function App() {
const [data, setData] = useState(exampleAPIDat);
const [filter, setFilter] = useState([]);
const filterFun = (event) => {
// (1) update your filter array
// category is passed from button
let filtering = event.target.value;
var newFilter;
if (filter.includes(filtering)) {
// remove if already in filter
newFilter = [...filter].filter((f) => f !== filtering);
} else {
// add if not in the filter
newFilter = [...filter, filtering];
}
setFilter(newFilter);
// (2) update your data accordingly
let newDat = exampleAPIDat.filter(
(book) => !newFilter.includes(book.category)
);
setData(newDat);
};
const FilterButtons = ({ books }) => {
// filter the data down to just categories
let set = books.map((book) => book.category);
let categories = [...new Set(set)];
// produce a button for each category in the dat
let btns = categories.map((category, index) => (
<button key={category + index} value={category} onClick={filterFun}>
{category}
</button>
));
return btns;
};
const AvailableBooks = ({ books }) =>
books.map((book, index) => (
<BookTile key={book.name + index} background={book.thumbnail}>
<h3>{book.name}</h3>
<h5>{book.category}</h5>
</BookTile>
));
return (
<div>
<ControlRow>
<FilterButtons books={exampleAPIDat} />
</ControlRow>
<Library>
<AvailableBooks books={data} />
</Library>
</div>
);
}
const ControlRow = styled.div`
display: flex;
flex-direction: row;
& button {
margin: 16px;
}
`;
const Library = styled.div`
display: flex;
flex-flow: row wrap;
`;
const BookTile = styled.div`
display: flex;
flex-direction: column;
justify-content: flex-end;
width: 200px;
height: 400px;
margin: 20px;
background-image: linear-gradient(
to top,
rgba(255, 255, 255, 1),
rgba(255, 255, 255, 0)
),
url(${(props) => props.background});
background-repeat: no-repeat;
background-position: center;
background-size: 200px 400px;
-webkit-box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
-moz-box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
box-shadow: 10px 10px 5px 0px rgba(0, 0, 0, 0.75);
&:hover {
transform: scale(1.1);
}
& h3 {
background-color: white;
color: green;
}
& h5 {
background-color: black;
color: white;
}
`;
categoriesdata have theposts? In your handler, you can set a new state and usecategory.nameand then according to value, you can conditionally render the posts.