reactjs - 当我调用 useState 挂钩时重新渲染 React 组件
问题描述
useState()
当我调用hook inside时,我遇到了重新渲染 React 组件的问题image.onload()
。我希望组件在我调用后重新渲染一次setClassificationResult
,但由于某种原因,它一直在重新渲染,就像我有一些无限循环一样。这是我的代码:
const ImageClassification = React.memo(function() {
const [isModelLoaded, setModelLoaded] = useState(false);
const [uploadedFile, setUploadedFile] = useState();
const [classifier, setClassifier] = useState();
const [classificationResult, setClassificationResult] = useState();
useEffect(() => {
async function modelReady() {
setClassifier(
await MobileNet.load().then(model => {
setModelLoaded(true);
return model;
})
);
}
modelReady();
}, []);
function onDrop(acceptedFiles: File[]) {
setUploadedFile(acceptedFiles);
}
function prepareImage(inputFile: File) {
const image = new Image();
let fr = new FileReader();
fr.onload = function() {
if (fr !== null && typeof fr.result == "string") {
image.src = fr.result;
}
};
fr.readAsDataURL(inputFile);
image.onload = async function() {
const tensor: Tensor = tf.browser.fromPixels(image);
classifier.classify(tensor).then((result: any) => {
// Crazy re-rendering happens when I call this hook.
setClassificationResult(result);
console.log(result);
});
console.log("Tensor" + tensor);
};
}
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop });
return (
<React.Fragment>
{!isModelLoaded ? (
<CircularProgress />
) : (
<div {...getRootProps()}>
<input {...getInputProps()} />
{isDragActive ? (
<p>Drop the files here.. </p>
) : (
<p>Drag 'n' drop some files here, or click to select files</p>
)}
{uploadedFile &&
uploadedFile.map((item: File) => {
prepareImage(item);
return classificationResult
? classificationResult.map((result: any) => {
return (
<ClassificationResult
className={result.className}
probability={result.probability}
/>
);
})
: null;
})}
</div>
)}
</React.Fragment>
);
});
export default ImageClassification;
知道如何避免这种疯狂的重新渲染吗?
解决方案
您的组件存在生命周期问题,因为它prepareImage(item)
从您的return
html 值调用。这意味着您将在每次渲染时调用此函数,这就是为什么它会创建一些无限循环的疯狂重新渲染。
您需要重新考虑您的算法并将其移动到更好的位置。一个好的解决方案是只准备图像onDrop event
,所以它只完成一次。
function onDrop(acceptedFiles: File[]) {
setUploadedFile(acceptedFiles);
acceptedFiles.forEach(file => {
prepareImage(file);
});
}
然后可以在状态中存储一个应该显示和准备的 Image 数组。
推荐阅读
- postgresql - 在 Entity Framework Core 中为 PostgreSQL 表的计算列设置公式
- swift - 当标签栏在 tvOS 13 中没有焦点时,可以隐藏标签栏焦点吗?
- python - 如何在bash脚本中使用参数执行复杂的python脚本
- documentation - 我应该如何提供巨大的参考表?
- browserstack - X-ray + browserstack 我们希望将 X-ray 与 browserstack 集成
- python - 使用索引的模糊搜索
- python - Discord.py bot - 如何让机器人根据命令内容做出响应?
- ios - 如何知道从服务器获取的日期格式
- module - 重新导出实现而不导出定义
- vue.js - 从 onSSR 加载数据后如何更新输入中的数据?