Dean Arvin
Dean Arvin

Reputation: 115

How to filter() using values from state?

I've got a list of gyms in my area:

gyms = [
  {
    "name": "The Gym",
    "equipment": ["nothing"]
  },
  {
    "name": "24 Fitness",
    "equipment": ["kettlebell","barbell"]
  },
  {
    "name": "Gym studio",
    "equipment": ["jump rope","barbell","dumbbell"]
  },
]

I also have a class that has within its state the equipment I need for my next workout. Additionally, when I click the button I'd like handleClick() to filter out the gyms that have the equipment I need. Here's what I have so far:

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      neededEquipment: ["barbell","jump rope"],
      gym: ""
    }
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    this.setState({
      gym: Gyms.filter(gym => (
          gym.equipment.every(e => this.state.neededEquipment.has(e))
      ))
    })
  }

  render() {
    return(
      <div>
        <p>{this.state.gym}</p>
        <button onClick={this.handleClick}>Press</button>
      </div>
    )
  }
}

So far the button does not display anything on the screen, and I'd like [in this example] to show "Gym studio". I'm completely stuck with how to have handleClick() work properly. All help is very greatly appreciated.

Upvotes: 0

Views: 49

Answers (1)

CertainPerformance
CertainPerformance

Reputation: 370859

You need to go the other way around: when filtering, check that .every needed equipment in state is included in the gym's equipment array:

gym: Gyms.filter(gym => (
  this.state.neededEquipment.every(
    equip => gym.equipment.includes(equip)
  )
))

Also note that .has is a method for Sets, eg new Set(['foo', 'bar']) - to check that an array includes a value, use .includes instead. (You only have arrays here, so use .includes)

You'll also probably want to render the available gyms properly, perhaps by mapping to their names. Replace

<p>{this.state.gym}</p>

with something like

<p>
  {this.state.gym.map(gym => <div>{gym.name}</div>)}
</p>

(or by stringifying each gym, or by listing both the gym's name and its available equipment, or something)

Upvotes: 5

Related Questions