I am trying to add id from redux to the previous data on paymentData state which then is inserted into paymentservice.create function. This function sends a post request to the backend
But I check the post request and I did not see the id but previous data are on the state.
I console.log the paymentdata state it does not contain the id until next render.
How do I push the data to the paymentdata state so that it will reflect immediately?
const ValidatePin = ({ setPaymentData, paymentData, setOpenValidatePinModal, showValidatePinModal, confirmLoading = '' }) => {
const [form] = Form.useForm();
const [errorMessage, setErrorMessage] = useState('');
const [loading, setLoading] = useState(false);
const [validationError, setValidationError] = useState([]);
const { currentUser } = useSelector(state => state.user)
const [paymentData, setPaymentData] = useState({});
const handleCancelValidatePin = () => {
setOpenValidatePinModal(false)
}
const onFinish = async (values) => {
setLoading(true)
setErrorMessage("")
setValidationError("")
try {
var microtime = Date.now()
console.log("microtime is ", microtime)
const res = await UserServices.validatePin(values)
if (res.data.msg == "success") {
setLoading(false)
// setOpenValidatePinModal(false)
form.resetFields();
setPaymentData(prevState => ({
...prevState,
user_id: currentUser.id,
}))
console.log("##### data from payment ", paymentData)
PaymentServices.create(paymentData)
}
} catch (error) {
if (error) {
setErrorMessage(error.response.data.data)
if (error.response.data.errors) {
setValidationError(error.response.data.errors)
}
} else {
setErrorMessage("Network Error. Try Again.")
}
} finally {
setLoading(false)
form.resetFields();
}
};
console.log("payment data", paymentData)
const handleOk = () => {
setModalText('The modal will be closed after two seconds');
setConfirmLoading(true);
setTimeout(() => {
setOpen(false);
setConfirmLoading(false);
}, 2000);
};
return (
<div className='login'>
<Modal
title="Enter Pin"
open={showValidatePinModal}
confirmLoading={confirmLoading}
footer={null}
>
{errorMessage && (<div className='alert alert-danger'>{errorMessage}</div>)}
{loading && (<div className='alert alert-success'>Please Wait...</div>)}
{ValidationError && Object.keys(validationError).map((error, index) => (
<ValidationError
message={validationError[error][0]}
key={index}
/>
))}
<Form
form={form}
onFinish={onFinish}
layout="vertical"
>
<Form.Item label="Pin" required name="pin"
rules={[
{
required: true,
message: 'Pin is Required',
}]
}>
<Input placeholder="Enter Pin" />
</Form.Item>
<Button onClick={handleCancelValidatePin}>
Cancel
</Button>,
<Button type="primary" htmlType="submit" disabled={loading}>
Validate
</Button>,
</Form>
</Modal>
</div >
)
}
export default ValidatePin
2
Answers
Reacts useState changes are async. All the state changes are executed at the end of the function. So when you update the state, its still not updated until the function ends.
For example in this line
setLoading(true)
. If you try loggingconsole.log(loading)
, it will give false.If you want to have the data immediately then you can create the new state separately like this:
In your code, you have two separate
paymentData
state variables: one passed as a prop and another defined locally in the component. To fix the issue and ensure that thepaymentData
state reflects immediately, you need to remove the locally definedpaymentData
state and use the proppaymentData
directly.Here’s the updated code:
With this change, the
setPaymentData
function passed as a prop will update thepaymentData
state immediately, and you can use it directly inside theonFinish
function.