简体   繁体   English

如何将 React state 与动态过滤器组件结合使用?

[英]How do I use React state in combination with a dynamic filter component?

I have a filter component that filters a set of data.我有一个过滤器组件来过滤一组数据。 I want to output the filtered data to the DOM by using the filtered object in the local state.我想通过在本地 state 中使用过滤后的 object 将过滤后的数据 output 到 DOM。 I cannot figure out how to use state without reseting the filter input and I can also not figure out how to output the filtered data to the DOM without using state.我无法弄清楚如何在不重置过滤器输入的情况下使用 state,我也无法弄清楚如何在不使用 state 的情况下将过滤后的数据 output 到 DOM。

This is the dataset:这是数据集:

const data = [
{ Name: John,
Tags: [walking, senior, Amsterdam]
},
{Name: Chris,
Tags: [biking, junior, The Hague]
},
{Name: Marc,
Tags: [walking, junior, Amsterdam]
}

I want to filter this dataset based on the tags the client selects:我想根据客户选择的标签过滤这个数据集:

<select data-categorie={hobby} onChange={filterTagHandler}>
<option value='all'>All><option>
<option value='walking'>Walking><option>
<option value='biking'>Biking><option>
<select>

<select data-categorie={age} onChange={filterTagHandler}>
<option value='all'>All><option>
<option value='junior'>Junior><option>
<option value='senior'>Senior><option>
<select>

<select data-categorie={city} onChange={filterTagHandler}>
<option value='all'>All><option>
<option value='amsterdam'>Amsterdam><option>
<option value='the hague'>The Hague><option>
<select>

The filter select components are dynamically generated from client input.过滤器 select 组件是从客户端输入动态生成的。 Therefor there is just the filterTagHandler instead of a nameHandler, hobbyHandler, cityHandler.因此只有 filterTagHandler 而不是 nameHandler、hobbyHandler、cityHandler。

First thing is to handle the selected tags and create an array from the selected tags:首先是处理选定的标签并从选定的标签创建一个数组:

const selectedTagsArray = []

    const filterTagHandler = (e) => {
        const option = e.target.options

        const tagSelected = option[option.selectedIndex].value
        const categorie = e.target.dataset.categorie

        selectedTagsArray.push(tagSelected)

        // Handle new option in categorie
        handleNewOptionInCategorie(categorie, tagSelected)

        // Handle all option
        handleAllOption(tagSelected)

        // Filter items
        filterItems(selectedTagsArray)
    }

So the first thing that happens in this onChange function is the selected tag is push to the selectedTagsArray.所以在这个 onChange function 中发生的第一件事就是选择的标签被推送到 selectedTagsArray。 If I would set the selectedTagsArray to state:如果我将 selectedTagsArray 设置为 state:

const [tagsArray, setTagsArray] = useState([])

setTagsArray(selectedTagsArray)

the selectedTagsArray would be emptied every time the client selects a new filter option, because the state get's updated.每次客户端选择新的过滤器选项时, selectedTagsArray 都会被清空,因为 state 已更新。 So that's no good.所以这不好。

So first I use some logic to update the selectTagsArray if the client selects a new option within a categorie (select component):因此,如果客户端在类别中选择新选项(选择组件),首先我使用一些逻辑来更新 selectTagsArray:

const handleNewOptionInCategorie = (categorie, tagSelected) => {
        filterTags && filterTags[categorie].forEach((tag) => {
            if(selectedTagsArray.includes(tag.Tag) && tag.Tag !== tagSelected){
                const index = selectedTagsArray.indexOf(tag.Tag)
                selectedTagsArray.splice(index, 1)
            }
        })
    }

Then I handle the 'All' option:然后我处理“全部”选项:

const handleAllOption = (tagSelected) => {
        if(tagSelected === 'All'){
            const index = selectedTagsArray.indexOf(tagSelected)
            selectedTagsArray.splice(index, 1)
        }
    }

This all works fine (as long as there is no state change along the way).这一切都很好(只要一路上没有 state 变化)。

Next I filter the data based on the selected tags:接下来我根据选定的标签过滤数据:

const filterItems = (array) => { const filterItems = (array) => {

    const newArray = []

    data.forEach(item => {

        if(array.every(tag => item.Tags.includes(tag))){
            newArray.push(item)
        }
    })
}

So this gives me the filtered data in the newArray object.所以这给了我 newArray object 中的过滤数据。 The next logical step now would be to:现在的下一个合乎逻辑的步骤是:

const [filteredItems, setFilteredItems] = useState(data)

setFilteredItems(newArray)

This has to be done inside the filteredItems object.这必须在filteredItems object 中完成。

But I cannot use state here as well, since the filterItems function is called inside the filterTaghandler onChange and so every time the client selects a new option the state updates and the selectedTagsArray is emptied.但是我也不能在这里使用 state,因为 filterItems function 在 filterTaghandler onChange 内部被调用,因此每次客户端选择一个新选项时,Z9ED39E2EA931586B76A985A6942EF5

So, how can I use the newArray object to update the DOM or how can I use state without emptying the selectedTagsArray?那么,如何使用 newArray object 来更新 DOM,或者如何在不清空 selectedTagsArray 的情况下使用 state?

I solved it by updating the state with the state.我通过用 state 更新 state 解决了这个问题。 It's a pretty simple solution, but it works.这是一个非常简单的解决方案,但它确实有效。

So instead of updating the selectedTagsArray if update the state like:因此,如果更新 state ,而不是更新 selectedTagsArray ,例如:

setFilterTags(...filterTags, tagSelected). setFilterTags(...filterTags, tagSelected)。 I'm using an onClick event to filter instead of it being called in the onChange.我正在使用 onClick 事件进行过滤,而不是在 onChange 中调用它。

I can now use the filterTags state to filter the data and update the data state to update the DOM.我现在可以使用 filterTags state 过滤数据并更新数据 state 来更新 DOM。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM