'setState data updating one iteration late in parent - ReactJS

The setState data in child is updating one iteration late in parent. My goal is that any time a value changes in child component I get the new updated field plus all the old ones in parent. The log line in parent shows the state data, all fields, but 1 iteration late. That is if I write "A" in Milestone Name console prints empty now if update it to "B" is shows "A" in console that is previous iteration

ConfigureCalenderForm.js (Parent Component)

import React, { useState } from 'react';
import MilestoneDetails from './MilestoneDetails';
import './ConfigureCalenderForm.css';

const ConfigureCalenderForm = () => {
  const milestoneDetailsChangeHandler = (milestoneDetails) => {
    console.log(milestoneDetails);
  };


  return (
    <div className='configure-calender__container'>
      <form>
        <MilestoneDetails
          onMilestoneDetailsUpdate={milestoneDetailsChangeHandler}
        />

        <div className='row configure-calender__actions'>
          <Button
            className='primary-blue small'
            icon={{
              color: '#fff',
              icon: 'checkMark',
              size: 'medium',
              isRequired: {},
            }}
            label='Save Milestone'
          />
        </div>
      </form>
    </div>
  );
};

export default ConfigureCalenderForm;

MilestoneDetails.js (Child Component)

import React, { useState } from 'react';
import './MilestoneDetails.css';

const MilestoneDetails = (props) => {
  const [enteredName, setEnteredName] = useState('');
  const [enteredDate, setEnteredDate] = useState('');
  const [enteredDescription, setEnteredDescription] = useState('');

  const nameChangedHandler = (event) => {
    setEnteredName(event.target.value);
    const milestoneDetails = {
      enteredName: enteredName,
      enteredDate: new Date(enteredDate),
      enteredDescription: enteredDescription,
    };

    props.onMilestoneDetailsUpdate(milestoneDetails);
  };

  const dateChangedHandler = (event) => {
    setEnteredDate(event.target.value);
    const milestoneDetails = {
      enteredName: enteredName,
      enteredDate: new Date(enteredDate),
      enteredDescription: enteredDescription,
    };

    props.onMilestoneDetailsUpdate(milestoneDetails);
  };

  const descriptionChangedHandler = (event) => {
    setEnteredDescription(event.target.value);
    const milestoneDetails = {
      enteredName: enteredName,
      enteredDate: new Date(enteredDate),
      enteredDescription: enteredDescription,
    };

    props.onMilestoneDetailsUpdate(milestoneDetails);
  };

  return (
    <div className='milestone__controls'>
      <div className='milestone__row'>
        <div className='milestone__control'>
          <label>Milestone Name</label>
          <input
            type='text'
            placeholder='Please Enter'
            value={enteredName}
            onChange={nameChangedHandler}
          />
        </div>

        <div className='milestone__control'>
          <label>Milestone Date</label>
          <input
            type='date'
            placeholder='Please Select'
            value={enteredDate}
            onChange={dateChangedHandler}
          />
        </div>
      </div>

      <div className='milestone__row'>
        <div className='milestone__controlTextArea'>
          <label>Milestone Description</label>
          <textarea
            className='milestone__TextArea'
            placeholder='Please Enter'
            maxLength={'50'}
            value={enteredDescription}
            onChange={descriptionChangedHandler}
          />
        </div>
      </div>
    </div>
  );
};

export default MilestoneDetails;


Solution 1:[1]

yes that is how the state works . you call setState then react would schedule an update to compute what it needs in the next render, so through out the execution of the function - dateChangeHandler for example - you still see the old state, and to send the new state to the parent send the event.target.value instead of enterdDate.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mahmed nabil