Проблемы с эффектом использования и проблемы с размонтированными компонентами

#javascript #reactjs #react-hooks #use-effect #use-state

Вопрос:

Я разрабатываю страницу react для стоматологической медицины в рамках проекта uni, и я довольно новичок в react и javascript.

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

мой функциональный код выглядит так:

 import { useState, useEffect } from "react";
import authHeader from "../../security/AuthHeader";
import axios from "axios";
import "../ToggleSwitch.css";

const ToggleSwitch = (userid) => {
  const API_URL = "http://localhost:8081/api/doh/";

  const switchState = {
    asthma: "off",
    infectiousDisease: "off",
    bleedingDisorder: "off",
    cancer: "off",
    diabetes: "off",
    epilepsy: "off",
    hivAids: "off",
    stroke: "off",
    heartDisease: "off",
    hbp: "off",
    immuneDisorders: "off",
    lungDisease: "off",
    mentalDisorder: "off",
    rheumaticDisease: "off",
    smokeTobaccoProducts: "off",
    radiationTherapy: "off",
    eatingDisorders: "off",
    entDisorders: "off",

    latex: "off",
    localAnasthetics: "off",
    metals: "off",
    penicillin: "off",
    pollen: "off",
    foods: "off",

    bleedingGums: "off",
    bruxism: "off",
    halitosis: "off",
    ulcer: "off",
    dryMouth: "off",
    soreJawM: "off",
  };

  const [patientInfo, setPatientInfo] = useState({
    name: "",
    surname: "",
    gender: "",
    dob: "",
  });

  const [message, setMessage] = useState();
  const [medications, setMedications] = useState("");
  const [otherInfo, setOtherInfo] = useState("");
  const [values, setValues] = useState({});

  
  const getDoH = async (userid) => {
    try {
      const auth = authHeader();
      let config = {
        headers: {
          "Content-Type": "application/json",
          Authorization: auth.Authorization,
        },
        params: {
          userid: userid,
        },
      };
      return await axios.get(API_URL   "getdohadmin", config);
    } catch (e) {
      console.log("Failet to get DoH");
    }
  };

  useEffect(() => {
    getDoH(userid).then(
        (response) => {
          let newValues = switchState;
          let valueArray = Object.entries(newValues).map((v, index) => {
            v[1] = response.data.switchValues[index];
            return v;
          });
          newValues = Object.fromEntries(valueArray);
          setValues({ ...newValues });
      
          newValues = patientInfo;
          valueArray = Object.entries(newValues).map((v, index) => {
            v[1] = response.data.patientInformation[index];
            return v;
          });
          newValues = Object.fromEntries(valueArray);
          setPatientInfo({ ...newValues });
  
          setMedications(response.data.medications);
          setOtherInfo(response.data.otherInfo);
        },
        (error) => {
          console.log(error);
        }
      );
  }, []);

  const handleChangeMed = (e) => {
    setMedications(e.target.value);
  };

  const handleChangeOtherInfo = (e) => {
    setOtherInfo(e.target.value);
  };

  const handleChangePatientInfo = (e) => {
    const { name, value } = e.target;
    setPatientInfo({
      ...patientInfo,
      [name]: value,
    });
  };

  const toggle = (name, value) => (e) => {
    console.log("Toggle", name, value);
    if (value === "off") {
      setValues({
        ...values,
        [name]: "on",
      });
    } else if (value === "on") {
      setValues({
        ...values,
        [name]: "off",
      });
    }
  };

  const upload = async (event) => {
    try {
      const auth = authHeader();
      let formData = new FormData();
      const switchValues = Object.values(values);
      const patientInformation = Object.values(patientInfo);

      formData.set("patientInformation", patientInformation);
      formData.set("switchValues", switchValues);
      formData.set("medications", medications);
      formData.set("otherInfo", otherInfo);

      event.preventDefault();

      setMessage("Declaration of health uploaded successfully!");

      return await axios.post(API_URL   "upload", formData, {
        headers: {
          "Content-Type": "application/json",
          Authorization: auth.Authorization,
        },
      });
    } catch (e) {
      setMessage("Declaration of health failed to upload!");
    }
  };

  //If you only want to run the function given to useEffect after the initial render,
  //you can give it an empty array as second argument.
  return {
    toggle,
    handleChangeMed,
    handleChangeOtherInfo,
    upload,
    handleChangePatientInfo,
    patientInfo,
    values,
    medications,
    otherInfo,
    message,
  };
};
export default ToggleSwitch;
 

Теперь в этом коде есть некоторые проблемы, связанные с частью useEffect.
Если я оставлю код таким образом, я получу следующее сообщение в консоли:

  Line 134:6:  React Hook useEffect has missing dependencies: 'patientInfo', 'switchState', and 'userid'. Either include them or remove the dependency array
 

также я замечаю в своем API, что эффект использования декларации о здоровье вызывается даже тогда, когда я обновляю другие страницы проекта, не связанные с декларацией о здоровье.

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

Также в консоли я иногда получаю это предупреждение:

 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
 

iv потратил часы, читая о useEffect, useinitialState и т. Д. Но я, кажется, не могу найти хорошее решение для этого.
Как я могу изменить этот код, чтобы не возникло утечки памяти или бесконечного цикла ?