过滤并推入数组后如何访问JSON文件

时间:2019-06-06 13:32:30

标签: json reactjs dictionary

我的天气应用程序有很大的问题。

我使用的是OpenweatherMap免费API,并且创建了一个包含两个选择输入的页面:一个用于从直接在州内陈述的对象数组中选择一个国家,第二个用于选择城市。

第二个选择非常棘手,因为我上传了一个巨大的JSON文件,其中包含API服务的所有城市的列表,并且我想过滤出不属于先前选择的国家/地区的每个城市。

我的问题是generateCitiesList()函数不会将经过过滤的元素传递到this.state.cityList

 import React from "react";
import ReactDOM from "react-dom";
import CITIES from "./cities.json";
import COUNTRIES from "./countries.json";
import "./styles.css";


   // So getCitiesByCountry accepts (country) parameter for which we use 
   // this.state.selectedCountry and filter how exactly?

   // Do we compare every element within cities.json file so that it returns
   // an object (array?) that meets the criteria of element.country being equal to
   // this.state.selectedCountry?

const getCitiesByCountry = (country) =>
  CITIES.filter(city => city.country === country);

// 

class App extends React.PureComponent {
  state = { selectedCoutnry: "" };

  handleOnSelectCountry = e => {
    this.setState({ selectedCoutnry: e.target.value });
  };

  render() {


      // What does this line of code do? It looks like an object destructurization
      // so should I assume that from now on
      // const selectedCountry is equal to this.state.selectedCountry ?

    const { selectedCoutnry } = this.state;


    return (
      <div className="App">
        <select value={selectedCoutnry} onChange={this.handleOnSelectCountry}>
          <option>Select a Country</option>

          // That makes a lot of sense. Why would I store countries list in state 
          while I could access it via JSON file.

          {COUNTRIES.map(({ name, id }) => (
            <option value={id} key={id}>
              {name}
            </option>
          ))}
        </select>
        {selectedCoutnry && (
          <select>
            <option>Select a City</option>

            // So we use a function getCitiesByCountry which returns a filtered object 
           //  which is then mapped through to render <option>s?

            {getCitiesByCountry(selectedCoutnry).map(({ name, id }) => (
              <option value={id} key={id}>
                {name}
              </option>
            ))}
          </select>
        )}
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

[   {     “ id”:707860,     “ name”:“ Hurzuf”,     “ country”:“ UA”,     “坐标”:{       “ lon”:34.283333,       “ lat”:44.549999     }   },   {     “ id”:519188,     “ name”:“ Novinki”,     “ country”:“ RU”,     “坐标”:{       “ lon”:37.666668,       “ lat”:55.683334     }   },   {     “ id”:1283378,     “ name”:“Gorkhā”,     “ country”:“ NP”,     “坐标”:{       “ lon”:84.633331,       “ lat”:28     }   } ]


4 个答案:

答案 0 :(得分:0)

看看是否适合您。

这代表城市的JSON。

cities: {
  city1: {
    cityName: 'City1',
    country: 'A'
  },
  city2: {
    cityName: 'City2',
    country: 'A'
  },
  city3: {
    cityName: 'City3',
    country: 'B'
  },
  city4: {
    cityName: 'City4',
    country: 'B'
  }
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state={
      selectedCountry: 'A',
      countries: ['A','B'],
      cities: {
       city1: {cityName: 'City1',
       country: 'A'},
       city2: {cityName: 'City2',
       country: 'A'},
       city3: {cityName: 'City3',
       country: 'B'},
       city4: {cityName: 'City4',
       country: 'B'},
      }
    }
    this.selectCountry = this.selectCountry.bind(this);
  }
  
  selectCountry() {
    this.setState((prevState) => {
      return({
        ...prevState,
        selectedCountry: prevState.selectedCountry === 'A' ? 'B' : 'A'
      });
    });
  }
  
  render() {
  
    let filteredCities = [];
    
    for (let i in this.state.cities) {
      this.state.selectedCountry === this.state.cities[i].country ?
        filteredCities.push(this.state.cities[i]) : null;
    }
    
    filteredCities = filteredCities.map((item)=> 
      <li>{item.cityName}</li>
    );
    
    return(
    <React.Fragment>
      <div>Selected Country: {this.state.selectedCountry}</div>
      <button onClick={this.selectCountry}>Change Country</button>
      <div>Country List</div>
      <div>
        <ul>
          {filteredCities}
        </ul>
      </div>
    </React.Fragment>
    );
  }
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

答案 1 :(得分:0)

这看起来很邪恶。不要直接改变状态。

   generateCitiesList = () => {
        const self = this;    
           self.state.cityList.push(citiesList.filter( function (countries) {

                return countries.country === `${self.state.country}`
            }));

        console.log(this.state.cityList);

        this.showCitiesList()  ===> WORKS, pushing desired objects into an array 
        };

将状态填充到生命周期函数componentDidMount

componentDidMount() {
  const cityList = citiesList.filter(element => element.country === this.state.country);

  this.setState({cityList});
}

答案 2 :(得分:0)

由于以下原因,您的代码无法正常工作:

citiesArray.push(filterCities)

应写为:

citiesArray.push(...filterCities)

但是您可以通过将代码减少为:

generateCitiesList = () => { 
    this.setState ({
        listCity: citiesList.filter(({country}) => (
            country === `${this.state.country}`;
        ))
    });
};

但是,在您的情况下,只应使用状态存储影响视图的最小数据-所选的国家/城市

当前所选国家/地区的城市列表不能成为州的一部分,因为它可以从所选国家/地区派生。 只需编写一个获取国家/地区的函数,然后返回该国家/地区的城市列表,然后在render()中针对所选国家/地区运行它即可:

render() {
    return (
        ...
        <select>
            {getCitiesByCountry(this.state.country).map(city => (
                <option value={city}>{city}</option>
            ))}
        </select>
        ...
    );
}

Edit vigorous-cdn-3kk92

答案 3 :(得分:0)

好吧,感谢@Yoav Kadosh(鸣谢!)我在下面是answear。

事实证明,为了有效地映射选定数量的项目,您应该:

  1. 创建一个返回过滤对象的函数

相反,您还可以应用链运算符,例如variable.filter((parameter)=> parameter> 2).map({element} => {element})。

  1. 映射上述函数的结果并将其推送到DOM
   constructor(props) {
       super(props);
       this.state = {
            country: '',
            city: '',
            result: {
               temperature: ''
            }
       }
   }


    handleCountrySelect = (e) => {
           this.setState({
               country: e.target.value
           });
           console.log(e.target.value);

    };


    filterCitiesByCountry = (country) => {
        return citiesJSON.filter ( city => city.country === country)

    };


    handleCitySelect = (e) => {
        this.setState ({
            city: e.target.value
        });

        console.log(e.target.value)

    };


    getWeather = async (e) => {
        e.preventDefault();

        fetch(`http://api.openweathermap.org/data/2.5/weather?q=${this.state.city},${this.state.country}&appid=${APIKEY}`)
            .then( res => res.json())
            .then( res =>
                this.setState ({
                    result: {
                        temperature: Math.round(res.main.temp - 273.15)
                    }
                })

            )
    };




    render() {

        return (

            <main>

                <section className='row text-center' id='weather_select_section'>
                <form>

                    <div className="countrySelect col-12 col-sm-6 text-center mt-5 mb-5 ">
                        <label> Select Country </label>

                        <select onChange={this.handleCountrySelect} required placeholder='Country...'>

                        <option value='' data-index='Country...'>  </option>

                        { countriesJSON.map(({name, code, key} ) => {
                            return (
                            <option value={code} key={key} > {name} </option>

                            )
                        })}
                    </select>
                    </div>


                    <div className="citySelect col-12 col-sm-6 text-center mt-5 mb-5 ">
                        <label> Select City </label>

                        {this.state.country && (
                            <select onChange={this.handleCitySelect} placeholder='City...' required>
                                <option value='' data-index='City...'></option>


                                { this.filterCitiesByCountry(this.state.country).map(({name, key}) =>
                                    <option value={name} key={key}> {name} </option>

                                )}

                            </select>
                        )

                        }

                    </div>

                    <button type='submit' onClick = {this.getWeather} className=" col-10 mt-5 mb-5 text-center "> Get Weather</button>


                </form>


                <div className=" col-12 WeatherInfoBox ">

                    <h3> Weather in {this.state.city}</h3>
                    <p> {this.state.result.temperature} &#8451;</p>