Mario D'Andrea
Mario D'Andrea

Reputation: 13

Why is use effect not triggering when it's array dependency changes?

So pretty much I have to do two API calls to get some data, I update state (two arrays: allOrgList, and patientOrgList) with this data. Next I need to compare these two arrays in state and find the difference between them, then update that to state.

What I'm trying to do is use useEffect to track those two arrays and when they change run the diffing function. However the useEffect that triggers this diffing function never gets called. Despite the fact that allOrgList and patientOrgList are going from empty arrays to arrays with multiple items.

I've tried making the dependency [allOrgList.length, patientOrgList.length] and [JSON.stringify(allOrgList.length), JSON.stringify(patientOrgList.length)] this will update my diffedOrgOptions state but it will keep calling the useEffect and I get a error saying too many rerenders.

Here's some code:

const [diffedOrgOptions, setDiffedOrgOptions] = useState([]);
const [allOrgList, setAllOrgList] = useState([]);
const [patientOrgList, setPatientOrgList] = useState([]);

  const getAllOrgs = () => {
    console.log('Get all org fires')
    const tempOrgList = [];

    trackPromise(
      GetAllOrganization()
        .then(data => {
          data.forEach(ele => tempOrgList.push({name: ele.name, organization_cis_id: ele.organization_cis_id}))
        })
        .then(setAllOrgList(tempOrgList))
        .catch(error => console.log(error))
    );
  };

  const getPatientOrgs = () => {
    const tempOrgList = [];

    props.patientDetails[0].organization_cis_ids.forEach(orgId => {
      trackPromise(
        GetOrganizationName(orgId)
          .then(data => tempOrgList.push({name: data[0].name, organization_cis_id: orgId}))
          .catch(error => console.log(error))
      )
    });

    setPatientOrgList(tempOrgList);
  };

  const diffOrgLists = () => {
    const tempDiffedOptions = [];
    const diffedList = allOrgList.filter(({ name: name1 }) => !patientOrgList.some(({ name: name2 }) => name2 === name1));
    diffedList.forEach(orgObj => tempDiffedOptions.push(({value: orgObj.organization_cis_id, label: orgObj.name})));
    setDiffedOrgOptions(tempDiffedOptions);
  };

  useEffect(() => {
    getPatientOrgs();
    getAllOrgs();
  }, []);

  useEffect(() => {
      if (allOrgList.length) {
      diffOrgLists();
    }
  }, [patientOrgList, allOrgList]);

Upvotes: 1

Views: 650

Answers (3)

user13227435
user13227435

Reputation:

I rewrite the code Try THIS CODE

const [diffedOrgOptions, setDiffedOrgOptions] = useState([]);
            const [allOrgList, setAllOrgList] = useState([]);
            const [patientOrgList, setPatientOrgList] = useState([]);

            const getAllOrgs = () => {
                console.log('Get all org fires')
                const tempOrgList = [];

                trackPromise(
                GetAllOrganization()
                    .then(data => {
                    data.forEach(ele => tempOrgList.push({name: ele.name, organization_cis_id: ele.organization_cis_id}))
                    })
                    .then(() => {
                        const differentData = diffOrgLists(tempOrgList)
                        setAllOrgList(tempOrgList)
                        setDiffedOrgOptions(differentData)
                    })
                    .catch(error => console.log(error))
                );
            };

            const getPatientOrgs = () => {
                const tempOrgList = [];

                props.patientDetails[0].organization_cis_ids.forEach(orgId => {
                trackPromise(
                    GetOrganizationName(orgId)
                    .then(data => tempOrgList.push({name: data[0].name, organization_cis_id: orgId}))
                    .catch(error => console.log(error))
                )
                });

                setPatientOrgList(tempOrgList);
            };

            const diffOrgLists = (allOrgList) => {
                const tempDiffedOptions = [];
                const diffedList = allOrgList.filter(({ name: name1 }) => !patientOrgList.some(({ name: name2 }) => name2 === name1));
                diffedList.forEach(orgObj => tempDiffedOptions.push(({value: orgObj.organization_cis_id, label: orgObj.name})));
                setDiffedOrgOptions(tempDiffedOptions);
            };

            useEffect(() => {
                getPatientOrgs();
                getAllOrgs();
            }, []);

Upvotes: -1

Julian Kleine
Julian Kleine

Reputation: 1547

some things wrong, I attempted to rewrite this in a more modern fashion, please have a detailed look. Also consider the usage of useMemo hook, as well as the map function, as this seems to be missing in your toolchain. I removed the usage of trackPromise, as I think this has been fully confusing for you. Start with working with async/await and then head over to the docs again and implement trackPromise with hooks.

  const [diffedOrgOptions, setDiffedOrgOptions] = useState([]);
  const [allOrgList, setAllOrgList] = useState([]);
  const [patientOrgList, setPatientOrgList] = useState([]);

  const getAllOrgs = useCallback(async () => {
    console.log("Get all org fires");
    const tempOrgList = (await GetAllOrganization()).map(
      ({ name, organization_cis_id }) => ({
        name,
        organization_cis_id
      })
    );
    setAllOrgList(tempOrgList);
  }, []);

  const getPatientOrgs = useCallback(async () => {
    const tempOrgList = await Promise.all(
      patientDetail.organization_cis_ids.map(async (orgId) => {
        const [{ name }] = await GetOrganizationName(orgId);
        return { name, organization_cis_id: orgId };
      })
    );
    setPatientOrgList(tempOrgList);
  }, [patientDetail.organization_cis_ids]);

  const diffOrgLists = useCallback(() => {
    const diffedList = allOrgList
      .filter(
        ({ name: name1 }) =>
          !patientOrgList.some(({ name: name2 }) => name2 === name1)
      )
      .map((orgObj) => ({
        value: orgObj.organization_cis_id,
        label: orgObj.name
      }));
    setDiffedOrgOptions(diffedList);
  }, [allOrgList, patientOrgList]);

  useEffect(() => {
    getPatientOrgs();
    getAllOrgs();
  }, [getPatientOrgs, getAllOrgs]);

  useEffect(() => {
    if (allOrgList.length) {
      diffOrgLists();
    }
  }, [diffOrgLists, allOrgList]);

Upvotes: 0

kelar
kelar

Reputation: 1

try this

            const [diffedOrgOptions, setDiffedOrgOptions] = useState([]);
            const [allOrgList, setAllOrgList] = useState([]);
            const [patientOrgList, setPatientOrgList] = useState([]);

            const getAllOrgs = () => {
                console.log('Get all org fires')
                const tempOrgList = [];

                trackPromise(
                GetAllOrganization()
                    .then(data => {
                    data.forEach(ele => tempOrgList.push({name: ele.name, organization_cis_id: ele.organization_cis_id}))
                    })
                    .then(() => {
                        const differentData = diffOrgLists(tempOrgList)
                        setAllOrgList(tempOrgList)
                        setDiffedOrgOptions(differentData)
                    })
                    .catch(error => console.log(error))
                );
            };

            const getPatientOrgs = () => {
                const tempOrgList = [];

                props.patientDetails[0].organization_cis_ids.forEach(orgId => {
                trackPromise(
                    GetOrganizationName(orgId)
                    .then(data => tempOrgList.push({name: data[0].name, organization_cis_id: orgId}))
                    .catch(error => console.log(error))
                )
                });

                setPatientOrgList(tempOrgList);
            };

            const diffOrgLists = (allOrgList) => {
                const tempDiffedOptions = [];
                const diffedList = allOrgList.filter(({ name: name1 }) => !patientOrgList.some(({ name: name2 }) => name2 === name1));
                diffedList.forEach(orgObj => tempDiffedOptions.push(({value: orgObj.organization_cis_id, label: orgObj.name})));
                setDiffedOrgOptions(tempDiffedOptions);
            };

            useEffect(() => {
                getPatientOrgs();
                getAllOrgs();
            }, []);

Upvotes: -1

Related Questions