Owenn
Owenn

Reputation: 1150

Javascript - How to filter but first checks if a state variable does not contain a certain value?

I have all my items in my original array called items and have a state that holds all of the filtered data:

const [filteredItems, setFilteredItems] = useState(items);

I have states for my filters as such:

const [filteredUser, setFilteredUser] = useState("");
const [filteredType, setFilteredType] = useState("");
const [filteredVariety, setFilteredVariety] = useState("");

This states are updated from <HTMLSelect /> components as such:

const handleUserSelect = (e) => {
    setFilteredUser(e.currentTarget.value);
}
// and so on...

<HTMLSelect onChange={handleUserSelect} />
<HTMLSelect onChange={handleTypeSelect} />
<HTMLSelect onChange={handleVarietySelect} />

Then I have a button that apply the filters to my data items:

const handleApplyFilters = () => {
    setFilteredItems(
        items.filter(obj => (
            obj.user === filteredUser;
            obj.type === filteredType;
            obj.variety === filteredVariety;
        ))
    )
}

<Button onClick={handleApplyFilters}>Apply Filters</Button>

However, the problem is that, if I want to filter ONLY the user for example. So I want the filter to only filter out a certain user. How can I modify my handleApplyFilters() function so that if only the filteredUser is selected, then it won't filter obj.type === "" (as filteredType in this case would be "" as nothing is being selected.

Upvotes: 0

Views: 48

Answers (2)

Nick Vu
Nick Vu

Reputation: 15520

In this case, you can reset filteredType and filterVariety states in handleUserSelect (whenever your user filter gets applied).

const handleUserSelect = (e) => {
    setFilteredUser(e.currentTarget.value);
    if(e.currentTarget.value) {
       setFilteredType("")
       setFilteredVariety("")
    }
}

Your filter application function also needs to be modified

const handleApplyFilters = () => {
    setFilteredItems(
        items.filter(obj => (
            (!filteredUser || obj.user === filteredUser) &&
            (!filteredType || obj.type === filteredType) &&
            (!filteredVariety || obj.variety === filteredVariety)
        ))
    )
}

Along with that, you also need to disable type and variety filters to prevent them get reselected.

Note that I don't see your HTMLSelect component, so I'd assume HTMLSelect has a disabled prop.

<HTMLSelect onChange={handleTypeSelect} disabled={filteredUser}/>
<HTMLSelect onChange={handleVarietySelect} disabled={filteredUser}/>

Upvotes: 0

Ori Drori
Ori Drori

Reputation: 191996

Change the condition so that filters that are equal to an empty string ('') would be evaluated to true and would skip the equality check to the the obj properties.

For example the expression

filteredType === '' || obj.type === filteredType

would be truthy if filteredType is an empty string.

Code:

const handleApplyFilters = () => {
  setFilteredItems(
    items.filter(obj => (
      (filteredUser === '' || obj.user === filteredUser) &&
      (filteredType === '' || obj.type === filteredType) &&
      (filteredVariety === '' || obj.variety === filteredVariety)
    ))
  )
}

You can shorten the expression a bit by using ! since !'' is true:

const handleApplyFilters = () => {
  setFilteredItems(
    items.filter(obj => (
      (!filteredUser || obj.user === filteredUser) &&
      (!filteredType || obj.type === filteredType) &&
      (!filteredVariety || obj.variety === filteredVariety)
    ))
  )
}

Upvotes: 1

Related Questions