Безумие рендеринга реакции

#reactjs #react-hooks #react-functional-component

#reactjs #реагирующие хуки #реагирующий функциональный компонент

Вопрос:

Я использую реагирующие хуки и функциональные компоненты. В моем функциональном компоненте происходят некоторые странные вещи, из которых я не могу найти выход. В useEffect изначально у меня не было возвращаемого массива, чтобы предотвратить бесконечный цикл, и я пытался использовать rowData в deleteClickedHandler, но он всегда пуст. После некоторого исследования выяснилось, что способ обойти это — использовать useRef , который, казалось, сработал, но вызвал гнев ESLinter, который потребовал, чтобы rowData был в массиве, который вызывает повторный рендеринг для useEffect . Это приводит к тому, что обработчик deleteClickedHandler получает данные из rowDataRef.current, но вызывает бесконечный цикл.

Обработчик deleteClickedHandler выполняет оптимистичный параллелизм, изменяет состояние rowData и взаимодействует с api.

Через несколько часов я не знаю, как это исправить.

Если я удаляю rowData из массива, который сообщает useEffect, когда нужно выполнить повторную визуализацию, обработчик удаления работает, но не выполняет повторную визуализацию, и поскольку deleteClickedHandler является обработчиком, я не могу определить, как вызвать повторную визуализацию без бесконечного цикла.

Я уверен, что делаю что-то глупое, но не могу определить, почему rowData недоступен в deleteClickedHandler — я знаю, что обработчик является формой замыкания, но rowData — это состояние.

 const initialState = {
  id: 0,
  credit: false,
  transactionAmount: 0,
  accountBalance: 0,
  transactionDate: new Date(),
  confirmation: "",
  comment: "",
  action: "EDIT",
};

const SERVER_URL='/api/checking';  //process.env.REACT_APP_SERVER_URL;

function Checking() {
  const [rowData, setRowData] = useState([]);
  const [newData, setNewData] = useState(initialState);
  const [displayModal, setModalDisplay] = useState(false);
  const columnDefinitions = Columns();
  const rowDataRef = useRef(rowData);

  useEffect(() => {
    fetch(SERVER_URL)
      .then((response) => response.json())
      .then((rowData) => setRowData(rowData));

    rowDataRef.current = rowData;
  }, [rowData]);

  function deleteClickedHandler(props) {
    let fetchUrl = SERVER_URL   "/"   props.id;
    let balance = 0.0;
    let transactionAmount = 0.0;
    let data = rowDataRef.current;

    if (
      data.length > 0 amp;amp;
      window.confirm("Are you sure you wish to delete transaction: "   props.id)
    ) {
      for (let i = 0; i < data.length; i  ) {
        transactionAmount = props.credit
          ? props.transactionAmount
          : -1.0 * props.transactionAmount;
        balance = balance   transactionAmount;

        if (data[i].id === props.id) {
          data.splice(i, 1);
        }

        if (data[i].id > props.id) {
          data[i].accountBalance = balance;
        }
      }

      setRowData(data);
      CustomFetch(fetchUrl, "DELETE");
    }
  }

  function rowActionHandler(props) {
    switch (props.action) {
      case "DELETE":
        deleteClickedHandler(props);
        break;
      default:
        break;
    }
  }

  const context = { componentParent: rowActionHandler };
  

Правка 1

Следующее очищает бесконечный рендеринг и позволяет удалению получить доступ к rowData через rowDataRef, но не выполняет повторный рендеринг после удаления. Как мне заставить повторный рендеринг при удалении работать?

   useEffect(() => {
    fetch(SERVER_URL)
      .then((response) => response.json())
      .then((rowData) => {
        setRowData(rowData)
        rowDataRef.current = rowData;
      });
  }, []);
  

Комментарии:

1. когда именно вы хотите useEffect запустить? Из того, что я вижу, сам эффект будет вызывать бесконечный повторный рендеринг запрос, помимо того, что вы описали выше.

2. Я хочу, чтобы он запускался при загрузке и при изменении rowData

Ответ №1:

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

 window.location.reload();