In my simple app I have two (styled-component's) inputs with type of date:
<DateInput
type="date"
name="startDate"
value={state.startDate}
onChange={(e) => handleInputChange(e)}
required
/>
<DateInput
type="date"
name="endDate"
value={state.endDate}
onChange={(e) => handleInputChange(e)}
required
/>
Every time I change the date of any of those inputs the function handleInputChange is being called:
const handleInputChange = (e) => {
setState({ ...state, [e.target.name]: e.target.value });
dataValidation(state);
};
This function updates the state with the new values from date inputs and then I'm running my dataValidation function where I'm passing my state to validate the dates (I'm checking if the start date is not greater than the end date). My problem is that when I pass this state it has older values, for example:
Input value: 01.01.2021
State value: 12.31.2019
Input value: 01.02.2021
State value: 01.01.2021
Input value 01.03.2021
State value: 01.02.2021
By that, I can't compare my dates. I see that this is some kind of latency for state updates. Can I somehow wait for my dataValidation function to run after the state will be updated?
State is updated asynchronously and the state is constant within a particular render of a react component. To see the updated state, component needs to re-render.
You can fix your problem using one of the following options:
Use the useEffect
hook that executes whenever your state is updated and the component has re-rendered. You can call the dataValidation
function from the useEffect
hook but then you need to add it in the dependency array.
useEffect(() => {
dataValidation(state);
}, [state, dataValidation]);
(Make sure you wrap the dataValidation
function in the useCallback
hook to avoid running the useEffect
hook infinitely).
Alternatively, you could move the code of the dataValidation
function inside the useEffect
hook.
useEffect(() => {
// write your data validation code here
}, [state]);
If you don't want to use the useEffect
hook, you could change the implementation of the handleInputChange
function as shown below:
const handleInputChange = (e) => {
// create an object representing the new state
const newState = { ...state, [e.target.name]: e.target.value };
// pass the "newState" object to both "setState" and
// "dataValidation" function
setState(newState);
dataValidation(newState);
};