2

I have a form that has various fields, and one of the fields contains an array of objects.

It pretty much adds an object that contains values from a subform of the main form.

const addNode = () => {
    let p_form = pForm
    let ha = [vForm, yForm, hForm]
    let info = [....]
    setCurrentNodeForm(
        {
            ...currentNodeForm,
            p: p_form,
            ha: ha,
            info: info,
        }
    )
    // inserts this form to a state called `addedNodes`
    let currArr = [...addedNodes]
    currArr.push(currentNodeForm)
    setAddedNodes(currArr)
    intializeForms()
}

This is the function that I use as an onClick function of my Add button.

This adds a new object to a state called addedNodes which is an array of objects.

Then when I submit my main form, I use the function below as an onClick function

const submitMainForm = () => {
    let credentials = [...]
    let nodes = [...addedNodes]
    setMainForm(
        {
            ...currentMainForm,
            credentials: credentials,
            nodes: nodes,
        }
    )

    let body = {
        name: .... // something
        objects: currentMainForm,
    }

    intializeForms()

    let options = {
        headers: header,
        method: 'post',
        mode: 'cors',
        body: JSON.stringify(body),
    }

    console.log('options.body', options.body)

    return new Promise((resolve, reject) => {
        fetch(endpoint, options)
            .then(res => res.json())
            .then(resText => {
                console.log('resText', resText)
            })
    }).catch(err => {
        console.log(err)
    })
}

What it does is, it updates the state currentMainForm using the current addedNodes object array that I have updated using the addNode function above. However, when I console.log the options.body as shown above, the objects field in the body is empty. Thus, when I send a POST request, the body is missing its critical part.

When I console.log the same thing outside the function, it shows up.

I wonder how I can guarantee the state to be updated properly inside the function.

Thanks in advance.

Dawn17
  • 7,825
  • 16
  • 57
  • 118

1 Answers1

1

Perform the side effect in React hook. if it's a functional component then add the api call in useEffect hook.

setMainForm is an async function, because of it's async nature you are getting no data in body.

What you can do, update the state in submit function, and use the useEffect hook to listen the change on the currentMainForm state and submit your data.

Example

useEffect( () => {
  fetchData();
}, [currentMainForm]);

const submitMainForm = () => {
  let credentials = [...]
  let nodes = [...addedNodes]
  setMainForm( prevState => {
    return  {
      ...currentMainForm,
      credentials: credentials,
      nodes: nodes,
    }
  });
}

function fetchData() {
  let body = {
    name: '....', // something
    objects: currentMainForm,
  }

  intializeForms()

  let options = {
      headers: header,
      method: 'post',
      mode: 'cors',
      body: JSON.stringify(body),
  }

  console.log('options.body', options.body)

  return new Promise((resolve, reject) => {
      fetch(endpoint, options)
          .then(res => res.json())
          .then(resText => {
              console.log('resText', resText)
          })
  }).catch(err => {
      console.log(err)
  })
}
Sohail Ashraf
  • 10,078
  • 2
  • 26
  • 42