Я пытаюсь использовать хук для сохранения состояния. Этот хук предоставляет ссылку на значение и простую функцию-мутатор. Я хотел бы иметь другой хук обновления, который использует указанный мутатор. В то время как в программе обновления значение верное, если у меня есть еще один хук, значение всегда является начальным значением. Вот пример, который воспроизводит проблему.
import React, { useEffect, useRef } from "react";
function useCounter() {
const counter = useRef<number>(0);
const increment = () => {
counter.current++;
};
return [counter, increment] as const;
}
function useUpdate() {
const [counter, increment] = useCounter();
console.log("rendering update");
return () => {
increment();
console.log(counter.current);
};
}
function useLoop() {
const update = useUpdate();
const [counter] = useCounter();
console.log("rendering loop");
return () => {
update();
console.log(counter.current);
};
}
export default function App() {
const loop = useLoop();
useEffect(() => {
const id = window.setInterval(loop, 1000);
return () => {
window.clearInterval(id);
};
}, [loop]);
return <div />;
}
Внутри useUpdate значение счетчика верное, но внутри useL oop это всегда 0. Я использую ref, потому что хуки не должны Не нужно перезапускать, когда счетчик меняется и поскольку он является объектом, функция, возвращаемая из l oop, должна брать его по ссылке и всегда должна иметь самое последнее значение, но это не так , Моя цель - использовать подобный шаблон для написания симуляции в сочетании с p5 js. Эта проблема совсем не связана с p5, поэтому я просто высмеял его функциональность обновления. Я пытался использовать useState, useCallback, но ничего не получалось.
Codesandbox
Я новичок в хуках, и этот шаблон может быть совершенно неверным. Я бы приветствовал советы по расширенной декомпозиции с крючками.
Спасибо!
РЕДАКТИРОВАТЬ:
Проблема в том, что useCounter запускается дважды и создает два разных, не связанных экземпляра. Вот мое предлагаемое решение для разложения состояний:
import React, { useEffect, useRef } from "react";
function useCounter() {
const counter = useRef<number>(0);
const increment = () => {
counter.current++;
};
return { counter, increment };
}
function useUpdate({ counter, increment }) {
console.log("rendering update");
return () => {
increment();
console.log(counter.current);
};
}
function useLoop(state) {
const update = useUpdate(state);
console.log("rendering loop");
return () => {
update();
console.log(state.counter.current);
};
}
export default function App() {
const state = useCounter();
const loop = useLoop(state);
useEffect(() => {
const id = window.setInterval(loop, 1000);
return () => {
window.clearInterval(id);
};
}, [loop]);
return <div />;
}