0

I'm trying to filter cards based off text fields that could be empty or could be filled out, if they are filled out then I want to filter everything that doesn't include that string out.

For example, if I just wanted to filter by the title "Test" I would only put something in the title input box, but if i wanted to filter by both title and composer I would have both text fields filled out and only the cards that matched with both text fields would show.

Currently how I'm trying to do it is as follows:

filterMusicLibrary() {
    let musicLibraryItems = [];
    this.state.musicGet.map(music => {
        if(music.title) {
            if(music.title.includes(this.state.title) ) {
                musicLibraryItems.push(
                    <MusicLibraryItem key= {music.id} music={music} history={this.props.history}/>
                );
            }
        }
        if(music.composer) {
            if(music.composer.includes(this.state.composer) ) {
                musicLibraryItems.push(
                    <MusicLibraryItem key= {music.id} music={music} history={this.props.history}/>
                );
            }
        }
        if(music.arranger) {
            if(music.arranger.includes(this.state.arranger) ) {
                musicLibraryItems.push(
                    <MusicLibraryItem key= {music.id} music={music} history={this.props.history}/>
                );
            }
        }
        if(music.instrumentation) {
            if(music.instrumentation.includes(this.state.instrumentation) ) {
                musicLibraryItems.push(
                    <MusicLibraryItem key= {music.id} music={music} history={this.props.history}/>
                );
            }
        }



    });

    musicLibraryItems = [..new Set(musicLibraryItems)]
    return musicLibraryItems;

}

I'm pushing everything to a musicLibraryItems array and then I was hoping to get the unique values by using the Set variable type from ES6 but it failed to work as intended, this way is also extremely inefficient and I was wondering if someone could help me find a solution.

1 Answer 1

1

Using a Set is not going to work as all items will be unique objects, but since the MusicLibraryItem component is the same for each case, you can express this quite elegantly with a filter:

filterMusicLibrary() {
  const filteredMusicItems = this.state.musicGet.filter((music) =>
    (!this.state.title || music.title && music.title.includes(this.state.title)) &&
    (!this.state.composer || music.composer && music.composer.includes(this.state.composer)) &&
    (!this.state.arranger || music.arranger && music.arranger.includes(this.state.arranger)) &&
    (!this.state.instrumentation || music.instrumentation && music.instrumentation.includes(this.state.instrumentation))
  );
  return filteredMusicItems.map((music) =>
    <MusicLibraryItem key={music.id} music={music} history={this.props.history}/>
  );
}
Sign up to request clarification or add additional context in comments.

3 Comments

This isn't filtering any of the items out correctly, the only one its able to filter out is one that has arranger and instrumentation as null values, although it does work when it's only filtering on one text field
Ah yes, I based it on the code (which is basicaly an or filter,) rather than your description. I've updated the answer to an and filter.
Thank you very much, all of that boolean logic got me extra confused, you saved me many hours!

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.