在渲染子元素之前加载数据

时间:2018-11-18 23:10:02

标签: javascript reactjs

我正在尝试根据外部JSON数据生成选择器选项列表。此处的代码大部分都很好,除了它的一部分在数据加载之前被调用而不会附加任何子代之外。我确定有一种方法可以实现此目的,但是我不确定对于我的特定情况该采用哪种方式。

这是代码:

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

    this.state = {value: "National", pokedexes: []};

    this.generatePokedexList();

    this.handleChange = this.handleChange.bind(this);
    this.generatePokedexList = this.generatePokedexList.bind(this);
    this.pokedexList = this.pokedexList.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  generatePokedexList() {
    const pokedexes = [];
    fetch("https://pokeapi.co/api/v2/pokedex/")
    .then(response => response.json())
    .then(myJson => {
      let results = myJson["results"];
      results.forEach(function(pokedex) {
        let pokedexName = pokedex["name"];
        let pokedexLink = "https://pokeapi.co/api/v2/pokedex/" + pokedexName;
        let pokedexDisplayName = capitalize(pokedexName.replace('-',' '));
        pokedexes.push(
          {
            name: pokedexName,
            displayName: pokedexDisplayName,
            link: pokedexLink
          }
        );
      });
      this.state.pokedexes = pokedexes;
      console.log(this.state.pokedexes)
    })
  }

  pokedexList() {
    if (this.state.pokedexes.length > 0) {
      console.log("listing")
      return (
        this.state.pokedexes.map(pokedex => (
          <option>{pokedex.displayName}</option>
        ))
      )
    }
  }

  render() {
    return (
      <select id="pokedex-selector" value={this.state.value} onChange={this.handleChange}>
        {this.pokedexList()}
      </select>
    )
  }

}

export default PokedexSelector;

我尝试如下使用componentDidMount(),但是在这种情况下(<select>元素),我不确定如何专门针对某个组件进行更改。

componentDidMount() {
    {this.pokedexList()}
  }

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:2)

您应该在触发render方法之前进行获取调用,最好在componentDidMount中进行,并将响应存储在状态中。仅当stateprops更改时,组件才会重新渲染。

state应该通过this.setState()方法进行更新,并且不应使用this.state直接进行突变。

在您的情况下,由于您尝试使用this.state直接更改状态,因此该组件将不会重新呈现。您应该将其替换为this.setState()

尝试此代码

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

    this.state = {value: "National", pokedexes: []};

    this.handleChange = this.handleChange.bind(this);
    this.generatePokedexList = this.generatePokedexList.bind(this);
    this.pokedexList = this.pokedexList.bind(this);
  }

  componentDidMount() {
    this.generatePokedexList();
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  generatePokedexList() {
    const pokedexes = [];
    fetch("https://pokeapi.co/api/v2/pokedex/")
    .then(response => response.json())
    .then(myJson => {
      let results = myJson["results"];
      results.forEach(function(pokedex) {
        let pokedexName = pokedex["name"];
        let pokedexLink = "https://pokeapi.co/api/v2/pokedex/" + pokedexName;
        let pokedexDisplayName = capitalize(pokedexName.replace('-',' '));
        pokedexes.push(
          {
            name: pokedexName,
            displayName: pokedexDisplayName,
            link: pokedexLink
          }
        );
      });
      this.setState({pokedexes: pokedexes}); // use setState()
    })
  }

  pokedexList() {
    if (this.state.pokedexes.length > 0) {
      console.log("listing")
      return (
        this.state.pokedexes.map(pokedex => (
          <option>{pokedex.displayName}</option>
        ))
      )
    }
  }

  render() {
    return (
      <select id="pokedex-selector" value={this.state.value} onChange={this.handleChange}>
        {this.pokedexList()}
      </select>
    )
  }

}

export default PokedexSelector;

答案 1 :(得分:0)

应该是this.setState而不是this.state.pokedexes = pokedexes。不要直接改变状态。

   this.setState({
          pokedexes
        })