由于setState,值变得不确定 [英] value becomes undefined because of setState

查看:62
本文介绍了由于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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆