create a dropdown in react to show/hide fetch data

2019-07-29 06:56发布

问题:

Currently I am calling the Riot Games api and displaying all the champions. I have added a filter by name section, but i would like to add a dropdown to sort by champion class. On initial page load I want every champion rendered (which it currently does), but then selecting a class from the dropdown only show the champs that have that class. I can show each champions class with {champion.table.tags} and adding the index number or numbers and this is what i want to be able to sort by. If {champion.table.tags[0} or {champion.table.tags[1} = "Fighter" for example. I would like every champion with a tag of "Fighter" to be shown when "Fighter" is selected in the dropdown

I'm pretty new to react and I have built this same feature in Rails without any problem, but I'm struggling with the React way of going about this.

my current code that shows all champs and has a sort function

import React, { Component } from 'react';
import { Link } from 'react-router';
import _ from 'lodash';

class Champions extends Component {
  constructor(props) {
    super(props);

    this.state = {
      champions: []
    };
  }

  componentWillMount() {
    fetch('http://localhost:3000/champ.json')
    .then(response => response.json())
    .then(champions => {
      this.setState({ champions })
    })
  }

  filter(e){
    this.setState({ filter: e.target.value} )
  }

  render() {
    let champions = this.state.champions;
    console.log('champions: ', champions);

    if(this.state.filter){
      champions = champions.filter( champion =>
      champion.table.name.toLowerCase()
      .includes(this.state.filter.toLowerCase()))
    }

    if(this.state.handleChange){
      tags = champions.handleChange( champion =>
      champion.table.tags
    .includes(this.state.handleChange()))
    }

    return (
      <div>
        <div>
          <input type="text"
                 placeholder="search for a champ"
                 onChange={this.filter.bind(this)}
          />
        </div>

        <div className="Sort">
          <select>
            {champions.map((champion, i) =>
              <option key={i}>{champion.table.tags[0]}
              </option>)}
          </select>
        </div>

      <ul className="champ-list">
        {champions.map(champion => {
          return <li key={champion.table.id} className="col-xs-3">
            <div>
              <Link to={`/${champion.table.id}`} >
              <img src={`http://ddragon.leagueoflegends.com/cdn/7.5.2/img/champion/${champion.table.image.full}`} />
              </Link>
              </div>
              <Link to={`/${champion.table.id}`} >
            <h3>{champion.table.key}</h3>
            <h4>{champion.table.title}</h4>
            <h4>{champion.table.tags}</h4>
            </Link>
          </li>
        })}
      </ul>
      </div>
    );
  }
}

export default Champions;

as of right now the dropdown goes through each champion object and populates the with the first class tag of every champion. I think there are maybe 7 classes total and I can manually create the if needed, but how can I show All of the champions and then just the ones based on the dropdown selection.

Not sure if this is relevant, but has also given me a bit of a headache in React. The JSON returns an array of 134 objects (champions). Inside each object are several key value pairs as well as more arrays with key value pairs inside of them. The class tags I am trying to sort by are inside of one of these nested arrays.

Any help or even a point in the right direction would be greatly appreciated

回答1:

figured it out on my own. here's the updated code

import React, { Component } from 'react';
import { Link } from 'react-router';
import _ from 'lodash';

class Champions extends Component {
  constructor(props) {
    super(props);

    this.state = {
      champions: [],
    };
  }


  componentWillMount() {
    fetch('http://localhost:3000/champ.json')
    .then(response => response.json())
    .then(champions => {
      this.setState({ champions })
      // console.log('setState: ', this.state.champions);
    })
  }

  filter(e){
    this.setState({filter: e.target.value})
  }

  filterChamp(e){
    this.setState({filterChamp: e.target.value})
  }


  render() {
    let champions = this.state.champions;
    // console.log(champions);
    // console.log('props: ', this.props);

    if(this.state.filter){
      champions = champions.filter( champion =>
      champion.table.name.toLowerCase()
      .includes(this.state.filter.toLowerCase()))
    }

    if(this.state.filterChamp){
      champions = champions.filter( champion =>
      champion.table.tags
      .includes(this.state.filterChamp))
    }

    return (
      <div>
        <select onChange={this.filterChamp.bind(this)} value={this.state.filterChamp}>
          <option value="">All Champs</option>
          <option value="Assassin">Assassin</option>
          <option value="Fighter">Fighter</option>
          <option value="Mage">Mage</option>
          <option value="Marksman">Marksman</option>
          <option value="Support">Support</option>
          <option value="Tank">Tank</option>
        </select>

        <input type="text"
               placeholder="search for a champ"
               onChange={this.filter.bind(this)}
        />
      <ul className="champ-list">
        {champions.map(champion => {
          return <li key={champion.table.id} className="col-xs-3">
            <div>
              <Link to={`/champ/${champion.table.name}`} >
              <img src={`http://ddragon.leagueoflegends.com/cdn/7.5.2/img/champion/${champion.table.image.full}`} />
              </Link>
              </div>
              <Link to={`/${champion.table.id}`} >
            <h3>{champion.table.key}</h3>
            <h4>{champion.table.title}</h4>
            </Link>
          </li>
        })}
      </ul>
      </div>
    );
  }
}

export default Champions;