Изменить состояние, обусловленное в useEffect, не вызывая ловушку и не нарушая правило исчерпывающих зависимостей - PullRequest
0 голосов
/ 06 ноября 2019

Я пытаюсь зарегистрировать мутацию inFlight в хуке useEffect. Регистрация должна происходить только в том случае, если мутация еще не была зарегистрирована. Таким образом, у меня есть булева переменная в состоянии, чтобы отслеживать, была ли мутация уже зарегистрирована, и я регистрируюсь условно на ее основе. Сразу после того, как я зарегистрировал мутацию в useEffect, я установил для этой переменной значение true. Следовательно, я установил его в false в моей функции отмены регистрации мутации сразу после того, как я выполню отмену регистрации.

Здесь возникает проблема: чтобы придерживаться исчерпывающего правила зависимости useEffect, я должен включить переменную логического состояния в массив зависимостей. Однако это означает, что как только я отменил регистрацию, useEffect запустится и перерегистрирует мутацию. Вместо этого я хочу, чтобы дерегистрация просто «подготовилась» к регистрации, и тогда регистрация происходила только после изменения определенного значения. Возможно ли это даже при соблюдении исчерпывающего правила зависимостей?

Я пытался изменить логическую переменную на ENUM, содержащую три состояния (AwaitingValueChange, ShouldDispatch, HasDispatched), только диспетчеризацию, если ее значением является ShouldDispatch, иустановите значение AwaitingValueChange в отмене регистрации. Затем я создал новый хук, который будет запускаться каждый раз, когда значение, которое должно вызывать изменения в регистрации, и устанавливал переменную состояния в ShouldDispatch, если его текущее значение - AwaitingValueChange. Тем не менее, новый хук также зависит от переменной состояния, поэтому я столкнулся с точно такой же проблемой, только на этот раз в цепочке вызовов: Deregister -> new hook -> old hook -> register вместо deregister -> old hook-> register.

Код регистра:

useEffect(() => {
  if (hasRegisteredMutationInFlight && inFlightDispatch) {
        inFlightDispatch({ type: 'registerMutation', mutationName });
        setHasRegisteredMutationInFlight(true);
      }
  }, [hasRegisteredMutationInFlight, ...]);

Код отмены регистрации:

const deregisterMutation = () => {
  inFlightDispatch({ type: 'deregisterMutation', mutationName });
  setHasRegisteredMutationInFlight(false);
};

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

1 Ответ

1 голос
/ 06 ноября 2019

Нельзя использовать один и тот же флаг для мутаций register и deregister. Это не имеет смысла вообще. Зачем вам нужно setHasRegisteredMutationInFlight (false) в deregisterMutation? Вы можете просто отменить регистрацию, и пока вы регистрируетесь на каком-либо значении, вы устанавливаете флаг в значение false, чтобы оно не зависело от того же значения. Просто рабочий пример того, что я имею в виду

Вы также можете сообщить мне, для какого конкретного случая использования вы подходите, чтобы я мог помочь вам больше

import React, { useEffect, useCallback, useState } from "react";
import ReactDOM from "react-dom";

const mutationName = "MUTATION_NAME";

function App() {
  const [type, setType] = useState("");
  const [isMutationSet, setMutationToRegister] = useState(true);
  const inFlightDispatch = useCallback(
    stuff => {
      setType(stuff.type);
    },
    [setType]
  );

  useEffect(() => {
    if (isMutationSet && inFlightDispatch) {
      inFlightDispatch({ type: "registerMutation", mutationName });
      setMutationToRegister(false);
    }
  }, [isMutationSet, inFlightDispatch]);

  const deregisterMutation = () => {
    inFlightDispatch({ type: "deregisterMutation", mutationName });
  };

  const registerMutation = () => {
    setMutationToRegister(true);
  };

  return (
    <div className="App">
      {type}
      <button onClick={deregisterMutation}>Degister</button>
      <button onClick={registerMutation}>Register</button>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

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