Кажется, что эти повторные визуализации происходят, потому что функция classifier.classify(gotResults)
будет выполняться много раз, и там вы обновляете состояние, используя setLabel(result)
, что вызовет повторную визуализацию каждый раз, когда она вызывается. Вы можете прокомментировать это и проверить, является ли это преступником. Если это так, то вам следует поверхностно сравнить results
с label
и обновлять состояние setLabel(result)
только в том случае, если эти объекты различаются:
Незначительно сравнивать result
с label
перед обновлением состояния :
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
без каких-либо аргументов, он будет выполнять этот хук при каждом рендере.
Использование эффекта Крюк
Запускается ли useEffect после каждого рендера? Да! По умолчанию он запускается как после первого рендера, так и после каждого обновления. (Позже мы поговорим о , как настроить это .) Вместо того, чтобы думать в терминах «монтажа» и «обновления», вам может показаться, что вам будет легче думать, что эффекты происходят «после рендеринга». React гарантирует, что DOM был обновлен к моменту запуска эффектов.
Этот хук будет выполняться при каждом рендере:
useEffect(() => {
let myp5 = new p5(sketch, myRef.current)
});
Добавить пустой массив в конец useEffect
перехватить, чтобы запустить его только один раз:
useEffect(() => {
let myp5 = new p5(sketch, myRef.current)
}, []);
ОБНОВЛЕНИЕ
Чтобы обновить метку на вашем существующем объекте P5, вам придется использовать redraw
. Вы должны создать ловушку эффекта для переменной состояния label
, которая будет вызываться при изменении label
:
// Set a P5 ref so you can use it again
const p5Ref = useRef();
// Change the initial hook to set the p5Ref
useEffect(() => {
p5Ref.current = new p5(sketch, myRef.current);
}, []);
// This effect will run only when the whole label object is updated,
// not just when a label.<prop> is updated
useEffect(() => {
// I'm not sure if that's going to work,
// you'll have to test and see how to force redraw using the P5 returned object properly
if (p5Ref && p5Ref.current) {
p5Ref.current.redraw();
}
}, [label]);
Конечно, эта ловушка не сработает, если вы просто измените label
значение из-за ссылки на объект, поэтому вам придется создавать новый объект при обновлении label
, используя setLabel
, например:
const gotResults = (error, result) => {
if (error) {
console.error(error);
} else {
// Create a new object so we'll get the update effect hook to trigger on label change
setLabel({ ...result });
classifier.classify(gotResults);
}
}