在启动渲染器中的函数(filterAndSort)之前,遇到状态未更新的问题。我在函数内添加了console.log语句,并且只有一种状态被更新。我的代码对我来说似乎合乎逻辑,因为我设置了一个if条件,仅在setState发生后才触发函数
完整错误消息:
警告:无法在已卸载的设备上调用setState(或forceUpdate) 零件。这是空操作,但表示您的内存泄漏 应用。要修复,请取消所有订阅和异步任务 在componentWillUnmount方法中。
但是,我怀疑是因为我有多个setState异步发生。
我在想,也许只有在获取所有axios请求之后,才需要将所有变量的componendDidMount重写为setState。 Multiple Axios Requests Into ReactJS State
我认为另一种解决方案是将函数的返回结果存储为状态而不是变量,然后添加componentDidUpdate。
componentDidUpdate(prevProps, prevState) {
if (this.state.value > prevState.value) {
this.filterAndSort();
}
}
组件
class Results extends Component {
constructor(){
super()
this.state = {
results: [],
races: [],
arr = []
isLoading: true
};
}
componentDidMount(){
const oneRequest = axios.get(URL_ONE)
.then(response =>
response.data.data.map(result => ({...
))
)
.then(results => this.setState({results, isLoading: false}))
const twoRequest = axios.get(URL_TWO)
.then(response =>
response.data.data.map(race => ({...}))
)
.then(races => this.setDefault(races))
}
setDefault = (races) => {
........
this.setState({arr, races, isLoading:false})
}
filterAndSort = (races, results) => {
console.log(races, results)
.......
}
render() {
const{races, results} = this.state
if (isLoading == true) {
return (
<div>
<p>Loading...</p>
</div>
)
} else {
return (
<div>
<BarChart
qualData={this.filterAndSort(races, results)}
raceData={this.filterAndSort(races, results)}
width="1200"
height="500" />
</div>
);
}
}
}
export default Results;
答案 0 :(得分:0)
好吧,我想到了很多事情。
首先,仅当您拥有两个数据中的一个(以先到者为准)时,才将isLoading设置为false,因此render方法有时会使用空的小数或结果来调用函数。 另一件事,您正在异步调用setState。在请求完成时,您的组件可能不再存在,因此它将尝试更新不存在的组件,并因该错误而失败。
对于第一个问题,一个可能的解决方案是为结果和比赛使用两个isLoading-variables。
对于第二个问题(在unmountComponent上调用setState),它有点复杂,因为您需要以某种方式取消请求。我建议阅读更多内容,一般建议是使用redux之类的库将数据移出组件。如果您用Google cancel promise on unmount
进行搜索,则会发现有关此问题的讨论。您还可以使用“ isMounted”变量来处理它,该变量将充当丑陋的补丁。
因此,一(或两个)请求完成后,将调用setState,然后重新呈现该组件。 isLoading现在为true,因此将使用结果(或竞赛)调用filterAndSort,但不会同时调用两者,因为第二个请求仍在等待处理。
最后,在您的render方法中,需要首先定义isLoading(我认为在您的代码中可以,但在问题中没有),并且is True比较可以更好地放在
if (isLoading) {
而不是if (isLoading == True) {
答案 1 :(得分:0)
您是对的。提出多个请求时,最好的做法是先等待所有 all 解决,然后再继续。为此,您可以使用内置在ES6中的Promise
库。另外,据我所知,为了获取数据,它的最佳做法是在componentWillMount()
中进行。我还要补充一点,this
的上下文在异步函数中时会发生变化。因此,在您的componentWillMount()
中:
let promiseArr = [axios.get(URL_ONE), axios.get(URL_TWO)];
let _this = this;
Promise.all(promiseArr)
.then((resp) => {
// Call _this.setState() here. Response from URL_ONE
// will be available in resp.data[0] and URL_TWO in resp.data[1]
}).catch((err) => {
console.log(err);
})
此外,在您的构造函数中:
constructor(){
super()
this.state = {
results: [],
races: [],
arr = []
isLoading: true
};
this.setDefault = this.setDefault.bind(this);
this.filterAndSort = this.filterAndSort.bind(this);
}
在调用这些方法时,使用.bind
确保this
的上下文引用该类的当前实例。
我认为做完这些事情后,错误就会消失。希望有帮助。