1

I'm trying to implement a multiple selection dropdown where users can filter accordingly, e.g. if Live and Scheduleis selected, only the results that have these two criteria should appear.

enter image description here

This is my current filtering function for the multi-select dropdown:

Filtering function & handleChange

 const displayBulletins = bulletins
    .filter((bulletin) => {
        if (optionSelected === '') {
            return bulletin
        } else if (bulletin.liveStatus.toLowerCase().includes(optionSelected.map(item => item.value))) {
            return bulletin
        }
        return false
    })

const handleChange = selected => {
        setOptionSelected(selected)
        console.log(selected, '--optionsSelected')
        console.log(selected.map(item => item.value), '--mappedOptionsSelected')
    };

enter image description here

My current issue is that, if I have only selected 1 of the live status options, the filtering works, but if I selected more than one option, it doesn't work and filters out nothing instead, so what I'm trying to achieve here is to make it work for multiple selections such as ["live", "schedule"] in this case or for all 3 cases.

Here's my code sandbox for reference:

Edit festive-pare-vhisn

2 Answers 2

2

The filter's callback should look something like this:

filter((bulletin) => {
  if (optionSelected.length === 0) {
    return true;
  } else {
    return optionSelected
      .map((item) => item.value)
      .includes(bulletin.liveStatus.toLowerCase());
  }
})

because you have to check if the optionSelected array has the liveStatus but not the other way around.

Here's the updated CodeSandbox:

Edit zealous-star-exzj2

BTW defining function components in the body of a function component causes unnecessary rerenders. In the case of react-select it causes focus issues, this is why the dropdown is not closing when clicked outside.

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for the help. Also, by defining function components in the body of a function component do you mean by how I'm putting react-select in DisplayBulletinSelect and using it in Bulletins? I'm still relatively new to ReactJS so I still don't really know what causes these unnecessary rerenders.
@Lance I'm referring to the function components like Option, ValueContainer, MultiValue etc. These should be defined outside Bulletins.
@Lance Yes, that looks good. You can see that the dropdown got fixed.
@Lance Improved the filter callback as we can directly return the boolean. Check the edited answer.
@Lance It works both ways because bulletin is a truthy value. Returning the returned value of includes just makes the callback a bit concise.
|
2

The problem here is that optionsSelected is an array and bulletin.liveStatus is an array, so you need to look if liveStatus is in the optionsSelected array

I modify with the following in the code sandbox and it worked.

Also, don't forget to add a Fragment with a key instead <> to allow React to perform well in re-rendering virtual DOM.

If you want to display all bulletins if no option is selected, instead of return false you should return true

  const displayBulletins = bulletins
    .filter((bulletin) => {
      if (optionSelected === []) {
        return bulletin;
      } else if (
        optionSelected
          .map((item) => item.value)
          .includes(bulletin.liveStatus.toLowerCase())
      ) {
        return bulletin;
      }
      return false;
    })
    .map((bulletin) => {
      return (
        <Fragment key={bulletin.bbID}>
          <BulletinList
            bulletin={bulletin}
            onDelete={onDelete}
          />
        </Fragment>
      );
    });

2 Comments

"If you want to display all bulletins if no option is selected, instead of return false you should return true" - No, the condition in the first if will always be false as you're comparing with a new array [] every time.
I see, thanks for the explanation and for the Fragment with key for better re-rendering performance tip as well.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.