1

Here is my problem:

I have two useEffects that I want to run to initialize my form values.

I need help figuring out the proper way to do this.

Here are the effects:


  useEffect(() => {
    if (fetchedIssue !== null) {
      setIssueUpdateArray(() => {
        return fetchedIssue.issueUpdates.map(issueUpdate => issueUpdate.issueUpdateGuid);
      });

      setActionArray(() => {
        return fetchedIssue.actions.map(action => action.actionGuid);
      });
    }
  }, [fetchedIssue]);

  useEffect(() => {
    if (fetchedIssue !== null) {
      populateFormObj(setValue, mapIssueToFormValues(fetchedIssue));
    } else {
      populateFormObj(setValue, defaultFormValues);
    }
  }, [fetchedIssue, setValue]);

But when I render the form it's empty and I think it's because of the setIssueArray and setActionArray happens after I run populateFormObj.

As far as I understand that is how setters work in React?

so my first approach was to combine them like so:

  useEffect(() => {
    const initializeForm = () => {
      if (fetchedIssue !== null) {
        setIssueUpdateArray(() => {
          return fetchedIssue.issueUpdates.map(issueUpdate => issueUpdate.issueUpdateGuid);
        });

         setActionArray(() => {
          return fetchedIssue.actions.map(action => action.actionGuid);
        });

        populateFormObj(setValue, mapIssueToFormValues(fetchedIssue));
      }
      else populateFormObj(setValue, defaultFormValues);

    };

    initializeForm()
  }, [fetchedIssue, setValue]);

And that still did not work, untill I made the initializeForm function async like this:

useEffect(() => {
    const initializeForm = async () => {
      if (fetchedIssue !== null) {
        await setIssueUpdateArray(() => {
          return fetchedIssue.issueUpdates.map(issueUpdate => issueUpdate.issueUpdateGuid);
        });

        await  setActionArray(() => {
          return fetchedIssue.actions.map(action => action.actionGuid);
        });

        populateFormObj(setValue, mapIssueToFormValues(fetchedIssue));
      }
      else populateFormObj(setValue, defaultFormValues);

    };

    initializeForm()
  }, [fetchedIssue, setValue]);

and it worked.

So far I haven't seen this being done so I want to know if this is bad practice and if there is a better way to achieve the same result.

Thanks

Hay Trần
  • 564
  • 4
  • 22

1 Answers1

0

Okay so I realised that I was looking at this the wrong way.

Here is what I came up with:


  useEffect(() => {
    if (fetchedIssue !== null) {
      const { mappedIssueUpdates } = mapIssueToFormValues(fetchedIssue);
      populateFormObj(setValue, mappedIssueUpdates);
    }
  }, [fetchedIssue, issueUpdateArray, setValue]);

  useEffect(() => {
    if (fetchedIssue !== null) {
      const { mappedActions } = mapIssueToFormValues(fetchedIssue);
      populateFormObj(setValue, mappedActions);
    }
  }, [actionsArray, fetchedIssue, setValue]);

  useEffect(() => {
    if (fetchedIssue !== null) {
      const { mappedValues } = mapIssueToFormValues(fetchedIssue);
      populateFormObj(setValue, mappedValues);
    } else {
      populateFormObj(setValue, defaultFormValues);
    }
  }, [fetchedIssue, setValue]);

each useEffect updates it's own part of the form. so whenever I update issueUpdateArray and actionArray I populate the form.