有时候,在对React项目进行评估时,我会遇到类似这样的事情:
export default () => new Promise((resolve, reject) => {
setTimeout(() => (Math.round(Math.random()) === 0 ? resolve(countries) : reject()), 100);
});
模拟可能有延迟或没有延迟的API。
我的问题是,当我想在React组件中(特别是在ComponentDidMount()
中获取此诺言时,我该怎么做才能确保render()
将等待此诺言来呈现所有内容我需要?围绕它的最佳实践是什么?
谢谢!
答案 0 :(得分:2)
这并不完全适用于使用随机延迟的promise。零延迟setTimeout
或立即解决的承诺将产生相同的结果,尽管几乎看不见。 render
的执行不能被推迟。
将以任何方式执行初始渲染。如果组件状态异步更改,则render
应该正确处理初始状态:
state = { data: null };
componentDidMount() {
Promise.resolve('foo').then(data => this.setState({ data }));
}
render() {
return this.state.data ? (
<div>{this.state.data}</div>
) : (
'No data'
);
}
答案 1 :(得分:1)
您无需执行任何操作。该组件在等待例如由模拟API调用的结果填充的某些状态。当承诺解决时,如果它在组件上设置了某些状态,则将使用新数据重新渲染组件。
答案 2 :(得分:1)
您可以在组件中拥有isLoading
状态,当承诺已解决时,您可以将其设置为false
,然后使用状态null
进行渲染。
示例
const countries = ["gb", "se"];
const getCountries = () =>
new Promise((resolve, reject) => {
setTimeout(
() => (Math.round(Math.random()) === 0 ? resolve(countries) : reject()),
2000
);
});
class App extends React.Component {
state = { isLoading: true, error: "", countries: [] };
componentDidMount() {
getCountries()
.then(countries => {
this.setState({ isLoading: false, countries });
})
.catch(() => {
this.setState({ isLoading: false, error: "Fetching countries failed" });
});
}
render() {
const { isLoading, error, countries } = this.state;
if (isLoading) {
return null;
}
if (error) {
return <div>{error}</div>;
}
return (
<div>
{countries.map(country => (
<div key={country}>{country}</div>
))}
</div>
);
}
}
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>
答案 3 :(得分:1)
您应该在状态中存储一个变量,该变量指示您的诺言是否完成。为此,您可以await
做出承诺并设置状态,也可以使用.then
并在函数的回调中设置状态。
最少的代码如下:
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {
show: false
}
}
componentDidMount = async () => {
try {
await new Promise((resolve, reject) => {
setTimeout(() => (Math.round(Math.random()) === 0 ? resolve(countries) : reject()), 100);
});
this.setState({ show: true })
} catch(err){
}
}
render = () => this.state.show ? <div>My content</div> : <div/>
}
您显然可以用导出的变量替换创建的Promise,并将呈现的组件更改为所需的任何内容。