在 React 中将数据从一个函数传递到另一个函数

我正在使用 P5 和 ML5,并在 React 中使用它们,这让我在让它们工作时不得不克服一些障碍。

我正在尝试获取标签名称,并将其绘制在网络摄像头上。我可以在 gotResults 函数中使用 console.log 记录标签名称,但我不知道如何将它用于 gotResults 函数之外的地方…

我刚开始学习编程,请原谅我 🙂

    import React, { useRef, useEffect, useState } from 'react';import p5, { VIDEO } from 'p5'import ml5 from 'ml5'const Webcam = props => {    const myRef = useRef();    const [label, setLabel] = useState([        { label: 'Starting Label', confidence: 0 },    ]);    useEffect(() => {        let myp5 = new p5(sketch, myRef.current)    });    const sketch = (p) => {        let mobilenet;        let cam;        let classifier;        let thumbUpRight;        let thumbDownRight;        let thumbUpLeft;        let thumbDownLeft;        let trainButton;        // let label = '';        const modelReady = () => {            console.log('Model is ready!');        }        const videoReady = () => {            console.log('Video is ready!');        }        const whileTraining = (loss) => {            if (loss == null) {                console.log('Training Complete')                classifier.classify(gotResults)            } else {                console.log(loss)            }        }        const gotResults = (error, result) => {            if (error) {                console.error(error);            } else {                // console.log(result)                setLabel(result);                classifier.classify(gotResults);            }        }        p.setup = () => {            p.createCanvas(640, 550);            cam = p.createCapture(VIDEO);            cam.hide();            p.background(0)            mobilenet = ml5.featureExtractor('MobileNet', modelReady)            classifier = mobilenet.classification(cam, videoReady)            thumbUpRight = p.createButton('Up Right');            thumbUpRight.mousePressed(function () {                classifier.addImage('thumbUpRight');            })            thumbDownRight = p.createButton('Down Right');            thumbDownRight.mousePressed(function () {                classifier.addImage('thumbDownRight');            })            thumbUpLeft = p.createButton('Up Left');            thumbUpLeft.mousePressed(function () {                classifier.addImage('thumbUpLeft');            })            thumbDownLeft = p.createButton('Down Left');            thumbDownLeft.mousePressed(function () {                classifier.addImage('thumbDownLeft');            })            trainButton = p.createButton('Train');            trainButton.mousePressed(function () {                classifier.train(whileTraining);            })        };        p.draw = () => {            p.background(0);            p.image(cam, 0, 0)            p.fill(255);            p.textSize(32);            p.text(label[0].label, 10, 530);        }    };    return (        <div ref={myRef}>        </div>    )}export default Webcam;

更新:所以错误与状态重置有关,每次调用 ML5 时都会重新渲染网络摄像头和所有内容?我猜想,每次它接触到 ML5 API 时都会重新绘制…?


回答:

看起来这些重新渲染是由于 classifier.classify(gotResults) 函数会执行多次,而你在这里使用 setLabel(result) 更新状态,这会导致每次调用时重新渲染。你可以注释掉它,看看是否是罪魁祸首。如果是的话,那么你应该浅比较 resultslabel,只有当这些对象不同时才更新状态 setLabel(result)

在更新状态之前浅比较 resultlabel

const gotResults = (error, result) => {  if (error) {    console.error(error);  } else {    if (!areEqualShallow(label, result) {      setLabel(result);    }    classifier.classify(gotResults);  }}function areEqualShallow(a, b) {  for (var key in a) {    if (a[key] !== b[key]) {      return false;    }  }  return true;}

如果这不是导致这些重新渲染的罪魁祸首,那么你应该检查你的 useEffect 钩子。我不知道你是否有意这样做,但如果没有参数的 useEffect 钩子,它会在每次渲染时执行这个钩子。

使用 Effect 钩子

useEffect 在每次渲染后都运行吗? 是的!默认情况下,它会在第一次渲染后和每次更新后运行。(我们稍后会讨论如何自定义这一点。)不要以“挂载”和“更新”的方式思考,你可能会发现以“渲染后”发生的效果来思考更容易。React 保证在运行效果时 DOM 已经更新了。

这个钩子会在每次渲染时运行:

useEffect(() => {  let myp5 = new p5(sketch, myRef.current)});

useEffect 钩子的末尾添加一个空数组,只运行一次:

useEffect(() => {  let myp5 = new p5(sketch, myRef.current)}, []);

更新

要更新现有 P5 对象上的标签,你必须使用 redraw。你需要在 label 状态变量上创建一个效果钩子,当 label 变化时它会被调用:

// 设置一个 P5 引用,以便你可以再次使用它const p5Ref = useRef();// 更改初始钩子以设置 p5RefuseEffect(() => {  p5Ref.current = new p5(sketch, myRef.current);}, []);// 当整个 label 对象更新时,这个效果将运行,// 而不是仅仅当 label.<prop> 更新时useEffect(() => {  // 我不能确定这是否会起作用,  // 你需要测试并查看如何使用返回的 P5 对象正确地强制重绘  if (p5Ref && p5Ref.current) {    p5Ref.current.redraw();  }}, [label]);

当然,由于对象引用,如果你只是更改 label 的值,这个钩子不会触发,所以在使用 setLabel 更新 label 时,你需要创建一个新对象,像这样:

const gotResults = (error, result) => {  if (error) {    console.error(error);  } else {    // 创建一个新对象,以便我们能在 label 更改时触发更新效果钩子    setLabel({ ...result });    classifier.classify(gotResults);  }}

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注