简体   繁体   中英

apply multiple filters react

I have 2 buttons which when clicked should filter by novelty or offer , I am able to make it so that when novelty is clicked it will filter by this but I am unable to make it so that if both are click it will filter by both novelty and offer

How can I make it so that when both novelty and offer are clicked it will filter by both of these?

https://www.webpackbin.com/bins/-KpVGNEN7ZuKAFODxuER

import React from 'react'

export default class extends React.Component {
  constructor() {
    super()

    this.state = {
      products: [
        { id: 1, novelty: true, offer: false, name: 'test1' },
        { id: 2, novelty: true, offer: true, name: 'test2' },
        { id: 3, novelty: false, offer: true, name: 'test3' } 
        ],
      display: 'all',
      filters: [
        {novelty:'true'},
        {offer: 'true'}
      ]
    }
  }

  setCategory (category) {
    this.setState({
      display: category 
    });
  }

 render() {
   return(
   <div>
      <button onClick={()=>this.setCategory(true)}>Akce</button>
      <button onClick={()=>this.setCategory(true)}>Offer</button>
           {
      this.state.products.filter( product => 
       products.offer === this.state.display ||
        this.state.display==='all')
        .map(product =>
         <div>{product.name}</div>
           )
            }
   </div>
    )
  }
}

Here is the final version I've come up with:

import React from 'react'

export default class extends React.Component {
  constructor() {
    super()

    this.state = {
      products: [
        { id: 1, novelty: true, offer: false, name: 'test1' },
        { id: 2, novelty: true, offer: true, name: 'test2' },
        { id: 3, novelty: false, offer: true, name: 'test3' } 
        ],
      filters: {
        novelty: true,
        offer: true
      }
    }
  }

  setCategory (category) {
    this.setState((state) => ({
      filters: Object.assign({}, state.filters, { [category]: !state.filters[category] })
    }));
  }

 render() {
   console.log(this.state.filters)
   return(
   <div>
      <button onClick={()=>this.setCategory('novelty')}>Akce</button>
      <button onClick={()=>this.setCategory('offer')}>Offer</button>
           { this.state.products
                       .filter(product => product.novelty === this.state.filters.novelty || product.offer === this.state.filters.offer)
                       .map(product =>
             <div key={product.id}>{product.name}</div>
           )}
   </div>
    )
  }
}

https://www.webpackbin.com/bins/-KpVHqfkjeraq6pGvHij

A few things:

  • Using a boolean instead of a string in your case is more adapted. ( true instead of 'true' ).
  • display: 'all' isn't required for your use case. You can compute this value from your filters if you need to.
  • setCategory receive which category you want to set as a param.
  • I would rename setCategory to setFilter

Also, I'm using the asycnhronous version of setState . This allows you to hand in a function.

this.setState((state) => ({
      filters: Object.assign({}, state.filters, { [category]: !state.filters[category] })
}));

Here I'm using Object.assign to create a new Object. I populate him with state.filters and finally I update the filter you want to. category will either be novelty or offer and thanks to that I'm using the shorthand version of [category] .

To conclude, I also update your filter function to check the product.novelty against the filter.novelty or the product.offer with the filter.offer

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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