Reputation: 317
I'm rendering a dropdown list of categories dynamically by storing the names of these categories in strings within an array and want to update my list of blog posts based on which category is selected in the dropdown.
The category array looks like this:
const tags = ['Sustainability', 'Electrical', 'Mechanical', 'Engineering']
I'm then mapping through this array to display these strings in a select tag dropdown like so:
<div className='col-span-8 md:col-span-2'>
<select
placeholder='Categories'
onChange={handleChange}>
<option value='' selected disabled hidden>
Choose Category
</option>
{tags.map((t) => (
<option>{t}</option>
))}
</select>
</div>
I then have a list of blogs coming from Prismic (headless CMS) which I have stored in state, and am mapping through to list them out in the UI. I've stored these in state called selectedBlogs like so:
const [selectedBlogs, setSelectedBlogs] = useState(blogs);
And mapped through like so (this just displays every blog currently)
{selectedBlogs.results.map((blog) => (
<SwiperSlide key={blog.data.title} className='blog-wrap1'>
<a
href={`/resource/${blog.slugs}`}
className='h-full object-cover'>
<img src={blog.data.image.url} alt='' />
<div className='absolute bottom-5 text-left text-white p-5 w-full font-header'>
<h1 className='text-2xl overflow-ellipsis'>
{RichText.asText(blog.data.title)}
</h1>
</div>{' '}
</a>
</SwiperSlide>
))}
Simply put, I want to update this list of blogs based on which Category is selected in this dropdown, and when it is selected filter the blogs and display only those within that category.
I know I need to use an onChange in the select tag which I have but how can I store the dropdown item which is selected and re-render my blog posts based on that?
Many thanks in advance for any guidance!
Upvotes: 0
Views: 306
Reputation: 356
I assume this is how you set your handleChange function, and after that do the following step :
const tags = ['Sustainability', 'Electrical', 'Mechanical', 'Engineering']
const [selectedBlogs, setSelectedBlogs] = useState(blogs);
/* you need this below state to store selected tag */
const [selectedTag, setSelectedTag] = useState("")
/* handle the value selected from the form option */
const handleChange = (e) => {
const selected_tag = e.target.value;
setSelectedTag(selected_tag)
}
useEffect(() => {
const filtered_blog = blogs.filter(blog => blog.data.tag === selectedTag);
setSelectedBlogs(filtered_blog)
}, [selectedTag]) // <--- listen to the changes on selectedTag that trigger this
// Then your selectedBlogs will update everytime you change the tag
Upvotes: 2
Reputation: 11
I would introduce a new state to set the filter like so:
const [filter, setFilter] = useState('')
And then set the state with an onClick() handler on the select element.
Since this is not an input-field where we can track the change of each letter, i wouldn't use onChange.
<option onClick={()=>setFilter(t)}></option>
You should be able to pass that state into a filter-function: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/filter
To make sure the filter-function runs whenever the state of our filter-state changes I would wrap it in a useEffect-hook:
The useEffect hook takes in a state at the end. The function inside the hook runs once whenever that state gets updated. I your case whenever you update the 'filter' state by clicking on a tag.
useEffect(()=>{
console.log(your-filterfunction)
},[filter])
Upvotes: 0