我想使用布尔变量使渲染仅在两个不同的提取都完成之后才有可能。我对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。
然后,当两者都完成后,状态为boolean hasSearched的值将设置为true,并且在完成两次提取后都将进行呈现。
这该怎么做?我的头快要爆炸了。谢谢。
最佳答案
只是关于setState
的几个注释。从react
文档:
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 })
})
希望它会有所帮助。