React:布尔变量,表示在渲染之前成功获取

时间:2018-01-08 19:10:23

标签: javascript reactjs asynchronous promise fetch-api

我想使用一个布尔变量,只有在完成两个不同的提取后才能进行渲染。我对React和JavaScript都很陌生,所以请耐心等待......

问题:

我的代码的相关部分:

class AddressBook extends Component {

  constructor() {
    super();
    this.state = {
      personData: [],
      projectData: [],
      hasSearched: false,
      simplePersonUrl: 'path-to-api/persons',
      simpleProjectUrl: 'path-to-api/projects',
    }
  }

  addressBookSearch(value) {
    var hasSearchedPersons = false;
    var hasSearchedProjects = false;

    if (value !== '' && value.length > 2) {
      const urlsToUse = this.apiUrlsToUse();

      fetch(`${urlsToUse["personUrl"]}${value}`)
        .then((response) => response.json()).then((responseJson) => {
        this.setState({personData: responseJson}).then(() => this.hasSearchedPersons = true)
      })

      fetch(`${urlsToUse["projectUrl"]}${value}`)
        .then((response) => response.json()).then((responseJson) => {
        this.setState({projectData: responseJson}).then(() => this.hasSearchedProjects = true)
      })
    }

    if (hasSearchedPersons == true && hasSearchedProjects == true) {
      this.setState({
        hasSearched: true
    });
    }
  }

}

然后我在render方法中有这个条件渲染:

{(this.state.hasSearched && (this.state.personData.length > 0 || this.state.projectData.length > 0)) &&
      <div>
        <Paper style={{boxShadow: 'none'}}>
          <SearchResultTab personData={this.state.personData} projectData={this.state.projectData}/>
        </Paper>
      </div>
}

{(this.state.hasSearched && this.state.personData.length <= 0 && this.state.projectData.length <= 0)
      ? <div style={{textAlign: 'center'}}>No results..</div>
      : null
}

渲染效果很好,但问题是渲染发生在渲染已经发生的第二次获取之前。 所以我现在试图用一些布尔值来阻止渲染。这是不起作用的部分。

现在,我知道承诺中的最后一部分是错误的,因为它给了我:

Uncaught (in promise) TypeError: Cannot read property 'then' of undefined

它就在那里表明我想做什么:

在成功完成提取时将boolean hasSearchedPersons和hasSearachedProjects设置为true。

然后,当两者都完成后,布尔值hasSearched,状态将被设置为true,并且渲染将在两次完成提取时发生。

怎么做?我的脑袋即将爆炸。谢谢。

1 个答案:

答案 0 :(得分:1)

关于setState的简单说明。来自react docs:

  

setState()将对组件状态的更改排入队列并告知React   这个组件及其子组件需要重新呈现   更新状态。

这意味着您一直在更改状态,使用setState重新渲染组件。在将hasSearch设置为true之前,您需要重新渲染两次组件。因此,为了避免不必要的重新渲染,您应该在fetch完成后使用它一次。 Promise.all()(已在评论中提及)可以使用。

Promise.all([
  fetch(`${urlsToUse["personUrl"]}${value}`),
  fetch(`${urlsToUse["projectUrl"]}${value}`)
]).then(responses => Promise.all(responses.map(res => res.json())
  .then(values => {
    // doing something with it.
    // once you are done use setState
    this.setState({ hasSearched: true })
  })

希望它会有所帮助。