【问题标题】:useEffect doesn't fire when data change数据更改时不会触发 useEffect
【发布时间】:2021-10-25 05:59:27
【问题描述】:

我创建了一个带有过滤器的表。每件事都运作良好。 后来,我想将过滤器从材质 ui 更改为 Core ui。 我创建了一个过滤器并尝试在移动之前对其进行测试。但它没有用。 useEffect 无论如何都不会触发的问题。我什至尝试放置变量 x 并在单击发生时将其递增,并将其作为参数放在 useEffect 中。但什么也没发生。

function renderTableData(每次我选择过滤器时都会渲染我的表格) 函数 onSiteChange(选择过滤器时的函数触发) 函数 UpdateTableData(将第一次提供我的表)

谢谢

******************************** RENDER TABLE *********************
  const renderTableData = () => {
    return (
      <div className="selectTable">
        <div
          className="ag-theme-alpine"
          style={{
            height: "75vh",
            width: "110wh",
            alignContent: "center",
            alignItems: "center",
            alignSelf: "center",
          }}
        >
          <AgGridReact
            rowData={dataFiltred}
            rowHeight={rowHeight}
            rowStyle={{ textAlign: "center" }}
          >
            <AgGridColumn field="Pseudo"></AgGridColumn>
            <AgGridColumn field="Site"></AgGridColumn>
            <AgGridColumn field="Langue"></AgGridColumn>
            <AgGridColumn field="Actif_Inactif"></AgGridColumn>
            <AgGridColumn field="Date_Formation"></AgGridColumn>
            <AgGridColumn field="Formateur"></AgGridColumn>
            <AgGridColumn field="Nature_Formation"></AgGridColumn>
            <AgGridColumn field="Durée"></AgGridColumn>
            <AgGridColumn field="Action"></AgGridColumn>
          </AgGridReact>
        </div>
      </div>
    );
  };

  // ********************************* logic *********************

  function onSiteChange(value, type) {
    if (type === "Site") {
      value.forEach((elem) => {
        rowData.forEach((data) => {
          if (data["Site"] === elem["value"]) {
            dataSiteFiltred.push(data);
          }
        });
      });
      console.log(dataSiteFiltred);
      if (dataSiteFiltred.length) {
        dataFiltred = [];
        dataSiteFiltred.forEach((elem94) => {
          dataFiltred.push(elem94);
        });
      }
    }
  }

  function updateTableData() {
    if (!dataFiltred.length) {
      rowData.forEach((elem) => {
        dataFiltred.push(elem);
      });
    }
  }
  updateTableData();

  useEffect(
    () => {
      renderTableData();
      console.log("fired");
    },
    [dataFiltred],
    [dataSiteFiltred]
  );

【问题讨论】:

  • useEffect(callback, [observables]) 而不是 useEffect(callback, [observable1], [observable2])

标签: javascript reactjs react-hooks use-effect core-ui


【解决方案1】:

这是完整的组件。

import React, { useEffect, useState, useRef } from "react";
import {
  CCard,
  CFormGroup,
  CCol,
  CLabel,
  CRow,
  CCardHeader,
  CButton,
  CCollapse,
} from "@coreui/react";

// AG GRID importaion
import { render } from "react-dom";
import { AgGridColumn, AgGridReact } from "ag-grid-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-alpine.css";

import CIcon from "@coreui/icons-react";
import { freeSet } from "@coreui/icons";
import Select from "react-select";

export default function ReacpFormationV2() {
  // golbal variables
  // var dataFiltred = []; // where we will push all filtred data
  // var dataSiteFiltred = []; // contain the data filtred using site
  // var siteFilterActive = false;
  // var dataMonthFiltred = []; // contain the data filtred using Month
  // var monthFilterActive = false;
  // var dataLangueFiltred = []; // contain the data filtred using Langue
  // var langueFilterActive = false;
  // var dataNatureFiltred = []; // contain the data filtred using Nature
  // var natureFilterActive = false;
  // var dataActifInactifFiltred = []; // contain the data filtred using Actif/Inactif
  // var actifInactifFilterActive = false;
  // var dataFormateurFiltred = []; // contain the data filtred using Formateur
  // var formateurFilterActive = false;
  //filtre collapse settings
  const [collapseFilter, setCollapseFilter] = useState(false);
  const toggleFilter = (e) => {
    setCollapseFilter(!collapseFilter);
    e.preventDefault();
  };
  // hooks
  const selectInputSiteRef = useRef();
  const selectInputMonthRef = useRef();
  const selectInputLangueRef = useRef();
  const selectInputNatureRef = useRef();
  const selectInputActifInactifRef = useRef();
  const selectInputFormateurRef = useRef();

  const [dataFiltred, setDataFiltred] = useState([]);
  const [dataSiteFiltred, setDataSiteFiltred] = useState([]);
  const [siteFilterActive, setSiteFilterActive] = useState(false);
  const [dataMonthFiltred, setDataMonthFilter] = useState([]);
  const [monthFilterActive, setMonthFilterActive] = useState(false);
  const [dataLangueFiltred, setDataLangueFiltred] = useState([]);
  const [langueFilterActive, setLangueFilterActive] = useState(false);
  const [dataNatureFiltred, setDataNatureFiltred] = useState([]);
  const [natureFilterActive, setNatureFilterActive] = useState(false);
  const [dataActifInactifFiltred, setDataActifInactifFiltred] = useState([]);
  const [actifInactifFilterActive, setActifInactifFilterActive] =
    useState(false);
  const [dataFormateurFiltred, setDataFormateurFiltred] = useState([]);
  const [formateurFilterActive, setFormateurFilterActive] = useState(false);

  // data
  const dataSite = [
    { value: "Sousse", label: "Sousse" },
    { value: "Tunis", label: "Tunis" },
    { value: "France", label: "France" },
  ];

  const dataMonth = [
    { value: "January", label: "January" },
    { value: "February", label: "February" },
    { value: "March", label: "March" },
    { value: "April", label: "April" },
    { value: "May", label: "May" },
    { value: "June", label: "June" },
    { value: "July", label: "July" },
    { value: "August", label: "August" },
    { value: "September", label: "September" },
    { value: "October", label: "October" },
    { value: "November", label: "November" },
    { value: "December", label: "December" },
  ];
  const dataLangue = [
    { value: "FR", label: "FR" },
    { value: "EN", label: "EN" },
    { value: "ES", label: "ES" },
  ];
  const dataNature = [
    { value: "upport Divinatoire", label: "upport Divinatoire" },
    { value: "Commerciale", label: "Commerciale" },
    { value: "Communication", label: "upport Divinatoire" },
    { value: "Culture Générale", label: "Culture Générale" },
    { value: "Divers", label: "Divers" },
  ];

  const dataActifInactif = [
    { value: "Actif", label: "Actif" },
    { value: "Inactif", label: "Inactif" },
  ];

  const dataFormateur = [
    { value: "SEMER", label: "SEMER" },
    { value: "Houssem", label: "Houssem" },
    { value: "Mehdi", label: "Mehdi" },
    { value: "Stéphane", label: "Stéphane" },
    { value: "Bassem", label: "Bassem" },
  ];

  // ********************************* TABLE DATA *********************
  const rowHeight = 50;
  const rowData = [
    {
      Pseudo: "Voy1",
      Site: "Tunis",
      Langue: "FR",
      Actif_Inactif: "Actif",
      Date_Formation: "January",
      Formateur: "Houssem",
      Nature_Formation: "Support Divinatoire",
      Durée: "4h",
      Action: "Visulaiser",
    },
    {
      Pseudo: "Voy2",
      Site: "Sousse",
      Langue: "EN",
      Actif_Inactif: "Inactif",
      Date_Formation: "",
      Formateur: "Si SEMER",
      Nature_Formation: "Commerciale",
      Durée: "",
      Action: "troller",
    },
    {
      Pseudo: "Voy3",
      Site: "France",
      Langue: "FR",
      Actif_Inactif: "Actif",
      Date_Formation: "February",
      Formateur: "Stéphane",
      Nature_Formation: "Communication",
      Durée: "03",
      Action: "Divers",
    },
    {
      Pseudo: "Voy4",
      Site: "",
      Langue: "ES",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "",
      Nature_Formation: "Culture Générale",
      Durée: "",
      Action: "Divers",
    },
    {
      Pseudo: "Voy5",
      Site: "",
      Langue: "",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "",
      Nature_Formation: "Divers",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy6",
      Site: "",
      Langue: "ES",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy7",
      Site: "",
      Langue: "ES",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "Mehdi",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy8",
      Site: "",
      Langue: "",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "SEMER",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy9",
      Site: "",
      Langue: "EN",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "Bassem",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy10",
      Site: "",
      Langue: "EN",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy11",
      Site: "",
      Langue: "EN",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
    {
      Pseudo: "Voy12",
      Site: "",
      Langue: "FR",
      Actif_Inactif: "",
      Date_Formation: "",
      Formateur: "",
      Nature_Formation: "",
      Durée: "",
      Action: "",
    },
  ];

  // ********************************* RENDER TABLE *********************
  const renderTableData = () => {
    return (
      <div className="selectTable">
        <div
          className="ag-theme-alpine"
          style={{
            height: "75vh",
            width: "110wh",
            alignContent: "center",
            alignItems: "center",
            alignSelf: "center",
          }}
        >
          <AgGridReact
            rowData={dataFiltred}
            rowHeight={rowHeight}
            rowStyle={{ textAlign: "center" }}
          >
            <AgGridColumn field="Pseudo"></AgGridColumn>
            <AgGridColumn field="Site"></AgGridColumn>
            <AgGridColumn field="Langue"></AgGridColumn>
            <AgGridColumn field="Actif_Inactif"></AgGridColumn>
            <AgGridColumn field="Date_Formation"></AgGridColumn>
            <AgGridColumn field="Formateur"></AgGridColumn>
            <AgGridColumn field="Nature_Formation"></AgGridColumn>
            <AgGridColumn field="Durée"></AgGridColumn>
            <AgGridColumn field="Action"></AgGridColumn>
          </AgGridReact>
        </div>
      </div>
    );
  };

  // ********************************* logic *********************

  function onSiteChange(value, type) {
    if (type === "Site") {
      value.forEach((elem) => {
        rowData.forEach((data) => {
          if (data["Site"] === elem["value"]) {
            setDataSiteFiltred([...dataSiteFiltred, data]);
          }
        });
      });
    }
    if (dataSiteFiltred.length) {
      setDataFiltred([]);
      dataSiteFiltred.forEach((elem) => {
        setDataFiltred([...dataFiltred, elem]);
      });
    }
  }

  function updateTableData() {
    if (!dataFiltred.length) {
      rowData.forEach((elem) => {
        setDataFiltred([...dataFiltred, elem]);
        console.log(dataFiltred);
      });
    }
  }
  updateTableData();

  useEffect(() => {
    renderTableData();
  }, [dataFiltred, dataSiteFiltred]);

  return (
    <>
      <CCard>
        <CCardHeader>
          <div
            style={{
              textAlign: "center",
              fontSize: "large",
              fontWeight: "bold",
            }}
          >
            Récapitulatif de formation continue
          </div>
        </CCardHeader>
      </CCard>
      <CCard>
        <CCardHeader>
          <CFormGroup row>
            <CCol md="6">
              <CButton
                className="btn-sm"
                size="sm"
                variant="outline"
                color="info"
                onClick={toggleFilter}
              >
                <CIcon size={"sm"} content={freeSet.cilFilter}></CIcon>
                Afficher Filtre
              </CButton>
            </CCol>
          </CFormGroup>
          <CFormGroup>
            <CCollapse show={collapseFilter}>
              <CFormGroup>
                <CCol md="6 mt-1">
                  <CRow>
                    <CCol md="2 mt-1">
                      <CLabel>Site:</CLabel>
                    </CCol>
                    <CCol md="8 mt-0">
                      <Select
                        isMulti
                        name="selectSite"
                        options={dataSite}
                        ref={selectInputSiteRef}
                        onChange={(value) => onSiteChange(value, "Site")}
                      />
                    </CCol>
                  </CRow>
                  <CRow>
                    <CCol md="2 mt-1">
                      <CLabel>Month:</CLabel>
                    </CCol>
                    <CCol md="8 mt-0">
                      <Select
                        isMulti
                        name="selectMonth"
                        id="selectMonth"
                        options={dataMonth}
                        ref={selectInputMonthRef}
                      />
                    </CCol>
                  </CRow>
                  <CRow>
                    <CCol md="2 mt-1">
                      <CLabel>Langue:</CLabel>
                    </CCol>
                    <CCol md="8 mt-0">
                      <Select
                        isMulti
                        name="SelectLangue"
                        options={dataLangue}
                        ref={selectInputLangueRef}
                      />
                    </CCol>
                  </CRow>
                  <CRow>
                    <CCol md="2 mt-1">
                      <CLabel>Nature:</CLabel>
                    </CCol>
                    <CCol md="8 mt-0">
                      <Select
                        isMulti
                        name="selectNature"
                        options={dataNature}
                        ref={selectInputNatureRef}
                      />
                    </CCol>
                  </CRow>
                  <CRow>
                    <CCol md="2 mt-1">
                      <CLabel>Actif/Inactif:</CLabel>
                    </CCol>
                    <CCol md="8 mt-0">
                      <Select
                        isMulti
                        name="selectAcifInactif"
                        options={dataActifInactif}
                        ref={selectInputActifInactifRef}
                      />
                    </CCol>
                  </CRow>
                  <CRow>
                    <CCol md="2 mt-1">
                      <CLabel>Formateur:</CLabel>
                    </CCol>
                    <CCol md="8 mt-0">
                      <Select
                        isMulti
                        name="selectFormateur"
                        options={dataFormateur}
                        ref={selectInputFormateurRef}
                      />
                    </CCol>
                  </CRow>
                </CCol>
              </CFormGroup>
            </CCollapse>
          </CFormGroup>
        </CCardHeader>
      </CCard>

      <div className="formationContinueContainer">
        {/* ********************** Table ****************** */}

        {renderTableData()}
      </div>
    </>
  );
}

【讨论】:

    【解决方案2】:

    您没有使用任何状态,或者更改了不会导致重新渲染和相应使用效果的状态或道具

    您需要将您的dataFiltreddataSiteFiltred 存储在一个状态中,然后更新它以导致重新渲染/使用效果。

    类似这样的:

    const [dataFiltred, setDataFiltred] = useState([]);
    

    并像这样更新您的状态:

    setDataFiltred([...dataFiltred, elem94]);
    

    useEffect 只接受一个依赖数组

    因此,如果您想同时查看两个数组,请执行以下操作:

     useEffect(
        () => {
          renderTableData();
          console.log("fired");
        },[dataFiltred, dataSiteFiltred]
      );
    

    如果改变数组后没有激活useEffect,可以考虑使用Array.length

     useEffect(
        () => {
          renderTableData();
          console.log("fired");
        },[dataFiltred.length, dataSiteFiltred.length]
      );
    

    【讨论】:

    • 这是一个很好的正确答案。我只是建议不要使用 length 属性。数组中总是有可能有不同的数据,但长度相同,因此效果不会触发。数组数据,如果被更改,应该是一个未变异的数据,在这种情况下Object.is 将认为后续值不同,并且效果将按预期触发。这符合不改变数据的一般建议。它有很大的好处,并且可以保持猜测。
    • @SEMERBENSALEM 您没有将阵列存储在某个状态。我更新了答案。
    • 我现在看到了更新,我测试了它并且它有效。我需要再次阅读我的代码并查看组件的呈现方式。因为在之前的解决方案中(使用材质 ui Select ),在创建状态时,数据不会呈现。我做了一些控制台日志,我发现当 useeffect 运行时,它会清空状态。我必须创建一个全局变量。无论如何,我真的很感谢你的帮助和善意。真诚的
    • 过滤器有效,但主要数据不再显示在表上,函数 updateTableData 在像这样更改后不再显示 if (!dataFiltred.length) { rowData.forEach((elem) => { setDataFiltred( [...dataFiltred, elem]); console.log(dataFiltred); });它只呈现 dara 的最后一个数组。我尝试在循环内使用 console.log(dataFiltred) 来检查每次里面有什么。我虽然每次只保留最后一个元素,但它每次都显示空数组如果你想看到钩子,我会在其他回复中添加完整的代码。
    【解决方案3】:

    所以这是以前的工作代码。 基本一样

    useEffect(
        () => {
          renderTableData();
        },
        [dataSiteFiltred],
        [dataMonthFiltred],
        [dataLangueFiltred],
        [dataNatureFiltred],
        [dataActifInactifFiltred],
        [dataFormateurFiltred],
        [dataFiltred]
      );
    
      function updateTableData() {
        var localData = [];
        if (!dataFiltred.length) {
          rowData.forEach((elem) => {
            dataFiltred.push(elem);
          });
        }
        if (
          dataFormateurFiltred.length ||
          dataActifInactifFiltred.length ||
          dataLangueFiltred.length ||
          dataMonthFiltred.length ||
          dataSiteFiltred.length ||
          dataNatureFiltred.length
        ) {
          localData = [
            ...dataFormateurFiltred,
            ...dataActifInactifFiltred,
            ...dataLangueFiltred,
            ...dataMonthFiltred,
            ...dataSiteFiltred,
            ...dataNatureFiltred,
          ];
          var dataForUser = [];
          dataFiltred = [];
          var exist = true;
          localData.forEach((elem) => {
            if (site.length && elem["Site"] !== site) {
              exist = false;
            }
            if (month.length && elem["Date_Formation"] !== month) {
              exist = false;
            }
            console.log(langue);
            if (langue.length && elem["Langue"] !== langue) {
              exist = false;
            }
            if (actifInactif.length && elem["Actif_Inactif"] !== actifInactif) {
              exist = false;
            }
            if (formateur.length && elem["Formateur"] !== formateur) {
              exist = false;
            }
            if (nature.length && elem["Nature_Formation"] !== nature) {
              exist = false;
            }
            if (exist === true) {
              dataForUser.push(elem);
            }
          });
          const seen = new Set();
          dataFiltred = dataForUser.filter((el) => {
            const duplicate = seen.has(el.id);
            seen.add(el.id);
            return !duplicate;
          });
        }
      }
      updateTableData();

    【讨论】:

    • 在你的问题中更新它,而不是创建一个新的答案,伙计。
    猜你喜欢
    • 1970-01-01
    • 2020-01-19
    • 1970-01-01
    • 2021-07-03
    • 1970-01-01
    • 2021-09-10
    • 2013-07-21
    • 2023-01-26
    • 2020-06-03
    相关资源
    最近更新 更多