如何存储Axios请求数据或保留Promise 实现React组件内多次复用
问题原因
你遇到的showData始终输出0的核心原因是Axios请求属于异步IO操作,调用getData()后不会等待请求返回结果就会立刻执行后续的this.showData(),此时接口响应还没回来,this.myData还未被赋值。
推荐实现方案
方案1:缓存Promise实例,支持多场景调用
Promise状态敲定(resolved/rejected)后,后续所有.then/await调用都会直接拿到对应结果,不会重复发起请求,是最符合你需求的实现:
constructor(props) { super(props); // 存储Promise实例做缓存 this.dataPromise = null; this.myData = []; this.getData = this.getData.bind(this); this.showData = this.showData.bind(this); } // 返回Promise实例,所有调用方共用同一个请求结果 getData() { if (!this.dataPromise) { // 仅首次调用发起请求,后续都复用缓存的Promise this.dataPromise = axios.get('/someEndpoint') .then(response => { const body = response.data; if(body) { this.myData.push(body); } // 把数据返回给所有后续调用的.then/await return this.myData; }) .catch(error => { console.log(error); throw error; // 保留错误状态给后续的catch处理 }); } return this.dataPromise; } async showData() { // 已完成的请求会立刻返回结果,未完成的会等待请求结束 const data = await this.getData(); console.log(data.length); } async componentDidMount() { await this.getData(); this.showData(); } render() { return( <button onClick={this.showData}> 展示数据 </button> ); }
方案2:结合React State + 加载状态(适合需要渲染到UI的场景)
如果你需要把请求到的数据渲染到页面上,用React内置的state存储是更符合React设计规范的方案,同时可以通过加载状态避免用户在请求完成前点击操作:
constructor(props) { super(props); this.state = { myData: [], isDataLoaded: false }; this.getData = this.getData.bind(this); this.showData = this.showData.bind(this); } getData() { axios.get('/someEndpoint') .then(response => { const body = response.data; if(body) { this.setState(prev => ({ myData: [...prev.myData, body], isDataLoaded: true })); } }) .catch(error => { console.log(error); }); } showData() { if (!this.state.isDataLoaded) { console.log('数据加载中,请稍后再试'); return; } console.log(this.state.myData.length); } componentDidMount() { this.getData(); } componentDidUpdate(prevProps, prevState) { // 数据加载完成后自动执行初始化操作 if (!prevState.isDataLoaded && this.state.isDataLoaded) { this.showData(); } } render() { return( <button onClick={this.showData} disabled={!this.state.isDataLoaded}> {this.state.isDataLoaded ? '展示数据' : '加载中'} </button> ); }
内容的提问来源于stack exchange,提问作者anesongib
相关产品推荐
相关产品推荐

