Значение из ловушки useRef React имеет только начальное значение - PullRequest
0 голосов
/ 16 апреля 2020

Я пытаюсь использовать хук для сохранения состояния. Этот хук предоставляет ссылку на значение и простую функцию-мутатор. Я хотел бы иметь другой хук обновления, который использует указанный мутатор. В то время как в программе обновления значение верное, если у меня есть еще один хук, значение всегда является начальным значением. Вот пример, который воспроизводит проблему.

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 />;
}

Ответы [ 2 ]

1 голос
/ 16 апреля 2020

В useLoop вы создали новую версию counter, которая отличается от той, которую вы объявили ранее. Чтобы решить эту проблему, вам нужно вернуть counter из useUpdate так:

function useUpdate() {
  const [counter, increment] = useCounter();

  console.log("rendering update");

  const incrementFunc = () => {
    increment();

    console.log(counter.current);
  };
  return [incrementFunc, counter]
}

function useLoop() {
  const [update, counter] = useUpdate();
  // const [counter] = useCounter(); this will be a new counter

  console.log("rendering loop");

  return () => {
    update();
    console.log(counter.current);
  };
}

0 голосов
/ 16 апреля 2020

Я думаю, что это проблема сферы. Вы инициализируете новую переменную-счетчик в useL oop, которая не зависит от переменной useUpdate. Вы должны вернуть переменную и ее функцию-мутатор из ловушки. Я внес следующие изменения в хуки useUpdate и useL oop, и, похоже, он работает так, как вы ожидали. опыт может ответить лучше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...