Búsqueda de sitios web

javascript - useRef: el estado se vuelve indefinido después del renderizado


Estoy usando ml5.js para entrenar un modelo de ML. Tengo que agregar imágenes al modelo usando la cámara web. La función de entrenamiento funciona bien con el código actual. Sin embargo, cuando intento establecer un estado dentro de mi sentencia if else dentro de la función train, lanza un error cuando intento testear usando el botón de prueba.

el valor de classifier se convierte en undefined.

export const Component: React.FC<ComponentProps> = (props: ComponentProps) => {
    let classifier: any;
         classifier = featureExtractor.classification(capture, videoReady);
    }

    
    function final() {
        classifier.classify(capture, (error, result) => {
            setPrediction(label);
            
        });
    }

    return (<div>
            <Button variant="contained" color="primary" onClick={() => final()}>testing!</Button>
        </div>
    </div>)
        ;
};

classifier es una variable, por lo que se volvería a renderizar cada vez. useRef podría usarse aquí, pero no pude averiguar cómo.

const classifier = useRef()
classifier.current

Acceder a ello de esta manera todavía me daba el error. También intenté crear un estado para el clasificador en sí, pero eso tampoco parecía funcionar para mí.

Aquí hay un Codesandbox para probar todo el asunto. Para ver el error, puedes establecer un estado en la declaración if else de la función train:

https://codesandbox.io/s/hardcore-solomon-zb34l?file=/src/Component.tsx

Respuesta #1

He proporcionado una versión bifurcada del Codesandbox que se mencionó arriba en los comentarios: https://codesandbox.io/s/frosty-sea-0pcfx?file=/src/Component.tsx. Esto contiene algunas correcciones, pero la mayoría está relacionada con cambiar las variables locales para capture y classifier y asignarlas a referencias. El siguiente código:

let capture: p5Types.Element;
let classifier: any;

fue cambiado a:

let capture: any = useRef<any>();
let classifier: any = useRef<any>();

Luego, todas las referencias a esas variables en las otras áreas del código se cambiaron a capture.current y classifier.current. Esas también podrían almacenarse en el estado, pero parecen ser asignadas y utilizadas únicamente fuera de los datos utilizados durante el renderizado y no requieren que el componente se vuelva a renderizar cada vez que se les asigna un valor.

Respuesta #2

Yo haría:

const { current: heap } = useRef({});

// In your `setup`
heap.classifier = featuresExtractor.classification(..);

// elsewhere access it as
heap.classifier

cuando escribiste:

const classifier = useRef()
classifier.current

classifier.current es persistente a través de los re-renderizados, pero aún necesitas asignarlo en setup como classifier.current=.... Prefiero la forma en que lo escribí, porque heap se convierte en un lugar conveniente para agregar cualquier otra cosa que deba ser persistente a través de los re-renderizados.