由于setState,值变得不确定 [英] value becomes undefined because of setState
问题描述
我正在使用p5和ml5.js通过网络摄像头添加一些图像来训练ML模型.火车功能可以像这样正常工作.但是,如果我取消对train函数中的if语句的注释:
I am using p5 and ml5.js to train an ML model by adding some images via my webcam. The train function works fine like this. However, if I uncomment the if statement within the train function:
if (lossValue == null)
classifier
的值,因为此后 undefined
,它将在下一步中引发错误.为什么会发生这种情况,我该如何解决?如果我只是在if语句中使用console.log,它不会产生问题.但是,如果我在其中使用setState,它会将分类器设置为undefined.
the value of classifier
because undefined
after that and it would throw an error in the next step. Why is this happening and how can I fix this?
If I just use a console.log inside the if statement, it doesn't create a problem. However, if I use the setState inside it, it sets the classifier to undefined.
export const Component: React.FC<ComponentProps> = (props: ComponentProps) => {
const [prediction, setPrediction] = useState<string>();
const [confidence, setConfidence] = useState<string>();
const [trainingComplete, setTrainingComplete] = useState<boolean>();
//const [lossValue, setLoss] = useState<any>();
let capture: p5Types.Element;
let classifier: any;
const setup = (p5: p5Types, canvasParentRef: Element) => {
capture = p5.createCapture(p5.VIDEO).parent(canvasParentRef);
const featureExtractor = ml5.featureExtractor('MobileNet', modelReady);
classifier = featureExtractor.classification(capture, videoReady);
}
const draw = (p5: p5Types) => {
}
function modelReady() {
console.log('Model Ready');
}
function videoReady() {
console.log('Video Ready');
}
function gotResult() {
console.log('classifier in results', classifier);
classifier.classify(capture, (err: any, result: any) => {
setPrediction(result[0].label);
});
}
function train() {
console.log('classifier in train', classifier);
classifier.train((lossValue: any) => {
console.log('Loss is', lossValue);
// if (lossValue == null){
// setTrainingComplete(true);
// }
});
console.log('classifier in train', classifier);
}
return (<div><Sketch setup={setup} draw={draw} className="sketch" />
<div className="button">
<Button variant="contained" color="primary" onClick={() => {classifier.addImage('first');console.log('image added')}}>First</Button>
<Button variant="contained" color="primary" onClick={() => {classifier.addImage('second');console.log('image added')}}>Second</Button>
</div>
<div className="secondbutton">
<Button variant="contained" color="primary" onClick={() => train()}>Train!</Button>
<Button variant="contained" color="primary" onClick={() => gotResult()}>Test!</Button>
<br />
{trainingComplete && (<span>Training Complete!</span>)}<br />
</div>
</div>)
;
};
代码和框:
https://codesandbox.io/s/hardcore-solomon-zb34l?file =/src/Component.tsx
推荐答案
您正在将分类器
定义为 let
变量.这不是状态,因此不会在重新渲染期间持续存在.每次重新渲染组件时,代码 let classifier:any;
被执行, classifier
变为 undefined
.
You are defining classifier
as a let
variable. It is not a state so it does not persist across re-renders. Every time your component gets re-rendered the code let classifier: any;
gets executed and classifier
becomes undefined
.
调用诸如 setTrainingComplete(true)
之类的 setState
函数时,这将更改组件的状态并导致其重新呈现.因此,您会丢失 classifier
的值.
When you call a setState
function such as setTrainingComplete(true)
this changes the state of your component and causes it to re-render. Therefore you lose the value of classifier
.
您想保留 classifier
的值,因此需要使用 useState
或 useRef
挂钩.在处理具有自己内部状态的外部库中的复杂对象时,通常使用 useRef
.这就是我的建议.
You want to keep the value of classifier
so you need to store it using a useState
or useRef
hook. I generally use useRef
when dealing with complex objects from external libraries which have their own internal state. So that's what I suggest here.
const classifierRef = useRef<any>();
function train() {
const classifier = classifierRef.current;
console.log('classifier in train', classifier);
classifier?.train((lossValue: any) => {
console.log('Loss is', lossValue);
if (lossValue == null) {
setTrainingComplete(true);
}
});
console.log('classifier in train', classifier);
}
这篇关于由于setState,值变得不确定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!