#javascript #reactjs #p5.js
#javascript #reactjs #p5.js
Вопрос:
Итак, я использую https://github.com/and-who/react-p5-wrapper для создания p5.js в React.
Мне интересно, есть ли способ передать значение из файла эскиза p5 обратно в React? Например. Я хочу отслеживать значение метки, сгенерированное в p5 Sketch, и использовать его где-нибудь позже. Как я могу сохранить это значение глобально?
export default function sketch(p5) {
function modelReady() {
console.log("Model is ready!!!")
mobilenet.predict(gotResults)
}
function gotResults(error, results) {
if (error) {
console.error(error)
} else {
**label = results[0].label** <-- This badboy
mobilenet.predict(gotResults)
}
}
То, что я создаю https://codesandbox.io/s/dark-wave-dgrlg (это камера машинного обучения, которая определяет, что видит камера) Вы можете видеть, что метка в React не обновляется, а обновляется только метка в эскизе p5.
Мое исправление: я сделал что-то подобное setInterval(setLabel, 0)
в своем коде, но, похоже, это не правильный шаблон? Есть ли лучший способ?
Комментарии:
1. если вы поместите этот код в логику монтирования, подобную
useEffect
компоненту react, вы можете сохранить эту информацию в состоянии react. или «более хакерские» способы, такие как помещение значения в объект window или в localstorage2. Здесь может помочь прокси . Он может использовать определенный обработчик для уведомления вашего компонента react о том, что произошло изменение значения метки. Можете ли вы также включить свой код react?
3. @DrewReese добавил сюда мой полный код: codesandbox.io/s/dark-wave-dgrlg
Ответ №1:
Как я могу сохранить это значение глобально?
Для глобальных состояний используйте хранилище redux. Вы можете отправить действие для сохранения этой метки.
ОБРАТИТЕ ВНИМАНИЕ, как указано в README,
myCustomRedrawAccordingToNewPropsHandler
функция вызывается, если свойства компонента-оболочки меняются
Итак, я делюсь объектом sketch, чтобы быть явным. Эта функция перерисовки будет использоваться для доступа к родительской функции, которая фактически отправляет в хранилище redux.
// sketch
export default function sketch(p) {
// use custom redraw handler
p.myCustomRedrawAccordingToNewPropsHandler = function (props) {
// TODO: replace with actual label
// get value out
setInterval(() => props.gotResults(null, "done"), 5000);
};
}
// action
const key = "p5";
const SAVE_LABEL = `${key}/SAVE_LABEL`;
// action creator
function saveLabel(label) {
return {
type: SAVE_LABEL,
payload: {
label
}
}
}
export default function Sketch(props) {
// dispatch inside component
const dispatch = useDispatch()
function gotResults(error, label) {
if (error) {
console.error(error);
return;
}
dispatch(saveLabel(label));
}
return (
<P5Wrapper
sketch={sketch}
gotResults={gotResults}
/>
);
}
// TODO: add reducer
Пример песочницы: https://codesandbox.io/s/pedantic-breeze-54mde
Комментарии:
1. Как OP получает
dispatch
и action creator в объект sketch, чтобыsketch
«отправить» его?2. это часть списка задач, который ведет к обучению. 🙂
3. Правильно… но
sketch
функция является p5.js объект, а неSketch
компонент react, поэтомуgotResults
его нет в React. Решает ли этот ответ или объясняет решение проблемы OP с получением значения из эскиза p5? По крайней мере, попытайтесь связать код вашего решения с кодом OP.4.
setInterval
было просто показать изменение состояния. В любом случае, вот грубый пример, показывающий нечто подобное. codesandbox.io/s/adoring-snow-l1qx35. Ах, круто! @JosephD. Спасибо! Я понял это. Я внес некоторые изменения в свой код. Теперь он работает (: codesandbox.io/s/jovial-gates-usew3 Это тебе за то, что ты мне так помог.
Ответ №2:
@josephD Я ломаю голову, пытаясь понять, как это работает в моем коде. Можете ли вы рассказать мне, как это работает? Спасибо!
Основываясь на этом файле, https://codesandbox.io/s/jovial-gates-usew3
Итак, в моем файле Sketch.tsx у меня есть такая строка команды props.setLabel(label)
— это создание React prop на лету? Мы вызываем его setLabel
и присваиваем ему значение label
?
p5.myCustomRedrawAccordingToNewPropsHandler = function (props) {
gotResults = (error, results) => {
if (error) {
console.error(error)
} else {
label = results[0].label
**props.setLabel(label)** <-- this bad boy
mobilenet.predict(gotResults)
}
}
}
Затем в нашем файле App.tsx кажется, что мы можем передать в setLabel
него prop, который мы создали из Sketch.tsx? Я думал, что для использования React.useState
мне нужно ввести что-то вроде setLabel(value)
? Нам не нужно вызывать setLabel(value)
что-либо в файле App.tsx?
const [label, setLabel] = React.useState("...")
return (
<>
<Frame>{label}</Frame>
<P5Wrapper sketch={sketch} setLabel={setLabel} /> <-- How this magic happen?
</>
)
Значение setLabel
из useState теперь является реквизитом в P5Wrapper? И он принимает setLabel
из Sketch.tsx в качестве атрибута?
Мое определение атрибута и prop: attribute={prop}
const [label, setLabel] = React.useState(«…»)
<P5Wrapper sketch={sketch} setLabel={setLabel} /> <— setLabel в качестве реквизита? Установить метку из Sketch.tsx в качестве атрибута?
Комментарии:
1. Эта концепция называется повышением состояния . Если состояние (
label
) находится в приложении (родительский компонент), то единственный способ обновить это состояние — черезsetLabel
.setLabel
in App передается как prop дочернему компоненту (P5Wrapper), чтобы дочерний компонент мог иметь средства для обновления родительского состояния.