![](/img/trans.png)
[英]Memory leak in React component whenever a delete function is run…not using useEffect?
[英]Unable to fix React/NextJS memory leak using useEffect() and cleanup function
我在页面上有一对功能组件挂钩, AddVocab
组件将新词添加到数组, ListVocab
映射该数组。
一切正常,直到我离开页面,然后出现此错误:
react_devtools_backend.js:3973 警告:无法对未安装的组件执行 React state 更新。 这是一个空操作,但它表明您的应用程序中存在 memory 泄漏。 要修复,请取消 useEffect 清理中的所有订阅和异步任务 function。
为了修复这个 memory 泄漏,我尝试了useEffect()
的许多变体和清理 function 但无济于事。 我知道原因是卸载组件时异步VocabDataService
Axios 调用未取消订阅/取消。
任何人都可以提供正确的useEffect()
和清理 function 吗?
以下是相关文件:
组件/vocab/ListVocab.js
import React, { useState, useEffect } from "react";
import VocabDataService from "../../services/vocab";
export default function VocabList() {
const [vocab, setVocab] = useState([]);
const [currentVocab, setCurrentVocab] = useState(null);
const retrieveVocab = () => {
VocabDataService.getAll()
.then((response) => {
setVocab(response.data);
})
.catch((e) => {
console.log(e);
});
};
useEffect(() => retrieveVocab());
const removeAllVocab = () => {
VocabDataService.deleteAll()
.then((response) => {
setCurrentVocab(null);
})
.catch((e) => {
console.log(e);
});
};
return (
<div>
<div>
<button onClick={removeAllVocab}>Delete</button>
<ul>
{vocab.map((vocab, index) => (
<li key={index}>{vocab.word}</li>
))}
</ul>
</div>
</div>
);
}
组件/vocab/AddVocab.js
import React, { useState } from "react";
import VocabDataService from "../../services/vocab";
export default function AddVocab() {
const [id, setId] = useState(null);
const [word, setWord] = useState("");
const [translation, setTranslation] = useState("");
const [starred, setStarred] = useState(false);
const [submitted, setSubmitted] = useState(false);
const onChangeWord = (e) => {
setWord(e.target.value);
};
const onChangeTranslation = (e) => {
setTranslation(e.target.value);
};
const saveVocab = () => {
var data = {
word: word,
translation: translation,
};
VocabDataService.create(data)
.then((response) => {
setId(response.data.id);
setWord(response.data.word);
setTranslation(response.data.translation);
setStarred(response.data.starred);
setSubmitted(true);
})
.catch((e) => {
console.log(e);
});
};
const newVocab = () => {
setId(null);
setWord("");
setTranslation("");
setStarred(false);
setSubmitted(false);
};
return (
<div className="submit-form">
{submitted ? (
<>{newVocab()}</>
) : (
<div>
<div className="form-group">
<label htmlFor="word">Word:</label>
<input
type="text"
className="form-control"
id="word"
required
value={word}
onChange={onChangeWord}
name="word"
/>
</div>
<div className="form-group">
<label htmlFor="translation">Translation:</label>
<input
type="text"
className="form-control"
id="translation"
required
value={translation}
onChange={onChangeTranslation}
name="translation"
/>
</div>
<button onClick={saveVocab} className="btn btn-success">
Submit
</button>
</div>
)}
</div>
);
}
页面/vocab.js
import React from "react";
import Routes from "../components/Routes";
import AddVocab from "../components/vocab/AddVocab";
import VocabList from "../components/vocab/VocabList";
export default function App() {
return (
<div>
<Routes />
<div>
<AddVocab />
<VocabList />
</div>
</div>
);
}
谢谢!
useEffect 在其返回语句中有一个清理 function。
尝试这个:
useEffect(() => {
let didCancel = false;
if (!didCancel ) {
retrieveVocab();
}
return() => {
canceled = true;
};
});
或相同的方法,但就在更新 state 之前(效果中包含 function):
useEffect(() => {
let didCancel = false;
VocabDataService.getAll()
.then((response) => {
if (!didCancel) {
setVocab(response.data);
}
})
.catch((e) => {
console.log(e);
});
return() => {
didCancel = true;
};
});
当需要“清理”时,React 将执行 function。 也就是说,当要卸载组件时。
注意:如果需要,可以使用 ref 而不是简单的变量。
看看React 文档
我希望这个对你有用
Memory 泄漏正在发生,因为您正在更新 state 而组件已卸载,因此在设置 state 时只需添加检查组件是否已安装。
if(mounted){
setVocab(data);
}
如果已安装,此链接将帮助您检查/设置。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.