使用 onChange 从 <select> 标记更新状态并过滤类别列表以显示该类别的博客文章

Posted

技术标签:

【中文标题】使用 onChange 从 <select> 标记更新状态并过滤类别列表以显示该类别的博客文章【英文标题】:Update state from <select> tag using onChange and filter through list of categories to display blog posts from that category 【发布时间】:2021-10-16 17:42:06 【问题描述】:

我通过将这些类别的名称存储在数组中的字符串中来动态呈现类别的下拉列表,并希望根据在下拉列表中选择的类别来更新我的博客文章列表。

类别数组如下所示:

const tags = ['Sustainability', 'Electrical', 'Mechanical', 'Engineering']

然后我通过这个数组进行映射,以在选择标记下拉列表中显示这些字符串,如下所示:

 <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>

然后,我有一个来自 Prismic(无头 CMS)的博客列表,我存储在状态中,并且正在映射以在 UI 中列出它们。我已将这些存储在名为 selectedBlogs 的状态中,如下所示:

  const [selectedBlogs, setSelectedBlogs] = useState(blogs);

并像这样映射(这仅显示当前的每个博客)

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>
          ))

简单地说,我想根据在此下拉列表中选择的类别来更新此博客列表,并在选择时过滤博客并仅显示该类别中的博客。

我知道我需要在我拥有的选择标签中使用 onChange,但我如何存储已选择的下拉项目并基于此重新呈现我的博客文章?

非常感谢您的任何指导!

【问题讨论】:

你的 handleChange 函数在哪里? 目前是空白的,因为我不确定要放什么。我试过让它接受一个事件并将 event.target.value 存储在一个新的状态中,如下所示: const handleChange = (e) => setItem(e.target.value);但不确定从这里去哪里,或者这是否正确 嘿,你看到我的回答了吗?希望对您有所帮助。 【参考方案1】:

我假设这是您设置 handleChange 函数的方式,然后执行以下步骤:

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

【讨论】:

是的,我想这是正确的答案。但考虑到value 属性应该添加到&lt;option&gt; 标签中。【参考方案2】:

我会引入一个新状态来设置过滤器,如下所示:

const [filter, setFilter] = useState('')

然后在选择元素上使用 onClick() 处理程序设置状态。

由于这不是我们可以跟踪每个字母变化的输入字段,所以我不会使用 onChange。

<option onClick=()=>setFilter(t)></option>

您应该能够将该状态传递给过滤器函数: https://developer.mozilla.org/en-US/docs/Web/javascript/Reference/Global_Objects/TypedArray/filter

为了确保过滤器功能在过滤器状态发生变化时运行,我会将其包装在 useEffect-hook 中:

useEffect 钩子在最后进入一个状态。每当该状态更新时,挂钩内的函数就会运行一次。每当您通过单击标签更新“过滤器”状态时,我就是您的情况。

useEffect(()=>
 
 console.log(your-filterfunction)

,[filter])

【讨论】:

以上是关于使用 onChange 从 <select> 标记更新状态并过滤类别列表以显示该类别的博客文章的主要内容,如果未能解决你的问题,请参考以下文章

Blazor:在使用 @bind 时如何在 <select> 中使用 onchange 事件?

<select>控件中,选中第一个值是不会触发onchange事件的,如何使选中第一值可以触发事件呢?

以编程方式更改值时触发Dojo Select onChange事件触发

js原生代码给select选择框实现onchange事件

AngularUI select2 onChange 方法

select中onchange的用法