Home > Software engineering >  React state not updating as expected, values in body not recognized by backend
React state not updating as expected, values in body not recognized by backend

Time:09-17

I have a component that is conditionally setting values based on a piece of state and a button click that passes the data object to RTK Query and sends to a controller. There are two aspects that are confusing me. First, the console log shows that the values getting set into state are the opposite of what they should be, and 2nd, the mongoose/express controller is not responding according to the values being passed in the req.body and just continues to provide the already existing values.

The button is the user way of toggle a submission or unsubmit, if submission is already true button correctly displays to unsubmit and onClick should set the values to false and 2 empty strings, but is providing the opposite. If submission is false, then the button is correctly displaying to submit, and the onClick should set the values to true and fill the strings, but is providing the opposite.

React component:

const Submit = ({ planId, plan, user, today}) => {

   const [isSubmitted, setIsSubmitted] = useState(plan.submitted);
   const [submitBy, setSubmitBy] = useState(plan.submittedBy);
   const [submitDate, setSubmitDate] = useState(plan.submittedDate);
   const [skip, setSkip] = useState(true)
   const [userId, setUserId] = useState()

    const [updateStatus] = useUpdateReportStatusMutation()

    const {data} = useGetUserQuery(userId, {skip})

    useEffect(() => {
        if(isSubmitted) {
              setUserId(plan.submittedBy),
              setSkip(false)
          }

    }, [isSubmitted])
   
     
     const onSubmit= async (data) => {
        console.log('onSubmit: ', data) //This shows the data as reflected by the onClick functions
                     
      try {
        const payload =  await updateStatus({ planId, data }).unwrap();
          console.log('fulfilled', payload) //continues to show the same already existing data
        } catch (err) {
          console.error('Failed to update report status: ', err)
        }
    
        toast.success("Report Status Updated", {
          position: toast.POSITION.TOP_RIGHT
        });
        
     }
    
    

    const handleUnsubmitValues = () => {

        setIsSubmitted(false)
        setSubmitBy('')
        setSubmitDate( '')
        console.log("values for unsubmit: ", isSubmitted, submitBy, submitDate) //this is currently logging- isSubmitted: true, submitBy: 'the users ID', submitDate: 'an ISO date string'


        handleSubmit()
        
    }

    const handleSubmitValues = () => {
        setIsSubmitted(true)
        setSubmitBy(user)
        setSubmitDate(today)
        console.log("values for submit", isSubmitted, submitBy, submitDate) //this is logging- isSubmitted: false, submitBy: '', submitDate: ''

        handleSubmit()
        
     }

     const handleSubmit = () => {
        const data = {
            submitted: isSubmitted,
            submittedBy: submitBy,
            submittedDate: submitDate
        }
        console.log("before submit", data) //this logs the same values as the function call
        onSubmit(data)

     }

     const subDate = new Date(plan.submittedDate).toLocaleDateString()

    return (
        <>
        
        {isSubmitted ? (
            
                <>
                    <CheckBoxIcon />
                    <label>{data?.fullName}</label><br />
                    <label>{subDate}</label><br />
                    <Button color='warning' variant='contained' onClick={handleUnsubmitValues}>Unsubmit</Button>
                </>
            
        ) :
            <>
                <CheckBoxOutlineBlankIcon />
                <Button color='primary' variant='contained' onClick={handleSubmitValues}>Submit Report</Button> 
            </>
        
                
        }
     <br />
     </>

    )
}

The mongoose/ express controller:

exports.updateReportStatus = async (req, res) => {
    console.log("req.body", req.body) //logs the values as supplied by the onSubmit
    try {
        const servicePlan = await ServicePlan.findOne({ _id: req.params.planId })
        if (req.body.submitted) {
            servicePlan.submitted = req.body.submitted
        }
        if (req.body.submittedBy) {
            servicePlan.submittedBy = req.body.submittedBy;
        }
        if (req.body.submittedDate) {
            servicePlan.submittedDate = req.body.submittedDate
        }
        if (req.body.approved) {
            servicePlan.approved = req.body.approved
        }
        if (req.body.approvedBy) {
            servicePlan.approvedBy = req.body.approvedBy;
        }
        if (req.body.approvedDate) {
            servicePlan.approvedDate = req.body.approvedDate
        }
        if (req.body.sent) {
            servicePlan.sent = req.body.sent
        }
        if (req.body.sentBy) {
            servicePlan.sentBy = req.body.sentBy;
        }
        if (req.body.sentTo) {
            servicePlan.sentTo = req.body.sentTo
        }
        if (req.body.sentDate) {
            servicePlan.sentDate = req.body.sentDate
        }
        console.log("status ", servicePlan) //logs the same existing values, regardless of req.body

        servicePlan.save()
        res.send(servicePlan)
    } catch (error) {
        res.status(404)
        res.send({ error: "Error updating report status", error})
    }
}

Console log of values for submit (should be true and filled strings):

values for submit false <empty string> <empty string> 
before submit 
Object { submitted: false, submittedBy: "", submittedDate: "" }

onSubmit:  
Object { submitted: false, submittedBy: "", submittedDate: "" }

console.log values for unsubmit (should be false and empty strings like above)

values for unsubmit:  true 62410a1dcaac9a3d0528de7a 2022-09-15T15:55:27.758Z 
before submit 
Object { submitted: true, submittedBy: "62410a1dcaac9a3d0528de7a", submittedDate: "2022-09-15T15:55:27.758Z" }

onSubmit:  
Object { submitted: true, submittedBy: "62410a1dcaac9a3d0528de7a", submittedDate: "2022-09-15T15:55:27.758Z" }

Heres a network call showing the body being passed in the request and the response not responding:

Network request

network response

For the state issue in recording and passing the values, I tried switching the functions being called by the onClick, but that just made it so the state controlling the button was not updating. My only guess at this point is there is a delay in the function calls between setting the state and passing the values to the handlesubmit on the frontend, as far as the backend not updating the model with the req.body values, I'm at a total loss.

I've looked at this for hours and hours now, so I'm probably just missing some details Any ideas or guidance is greatly appreciated.

CodePudding user response:

there might be something wrong with updateStatus function.

CodePudding user response:

So I got the frontend working correctly by bringing in React-Hook-Form and using register on the CheckBox Icons and setValue in the update functions. It doesn't explain why the state was not updating correctly to the provided values in the functions, so I'm at a loss there. At least now the values making it to the onSubmit call are appropriate to what what is being passed. The controller is still doing some funky stuff, but I'll post that as a separate question.

const Submit = ({ planId, plan, user, today}) => {

   const [isSubmitted, setIsSubmitted] = useState(plan.submitted);
   const [skip, setSkip] = useState(true)
   const [userId, setUserId] = useState()

    const [updateStatus] = useUpdateReportStatusMutation()

    const {data: hasUser} = useGetUserQuery(userId, {skip})

    useEffect(() => {
        if(isSubmitted) {
              setUserId(plan.submittedBy),
              setSkip(false)
          }

    }, [isSubmitted])

    const {register, handleSubmit, setValue} = useForm({
        defaultValues: {
            submitted: isSubmitted || false,
            submittedBy: plan.submittedBy || '',
            submittedDate: plan.submittedDate || ''
        }
    })
   
     
     const onSubmit= async (data) => {
        console.log('onSubmit: ', data)
                     
      try {
        const payload =  await updateStatus({ planId, data }).unwrap();
          console.log('fulfilled', payload)
        } catch (err) {
          console.error('Failed to update report status: ', err)
        }
    
        toast.success("Report Status Updated", {
          position: toast.POSITION.TOP_RIGHT
        });
        
     }
    
    

    const handleUnsubmitValues = () => {

        setIsSubmitted(false)
        setValue('submitted', false)
        setValue('submittedBy', '')
        setValue('submittedDate', '')        
    }

    const handleSubmitValues = () => {
        setIsSubmitted(true)
        setValue('submitted', true)
        setValue('submittedBy', user)
        setValue('submittedDate', today)
     }

    
     const subDate = new Date(plan.submittedDate).toLocaleDateString()

    return (
        <>
        
        {isSubmitted ? (
            
                <>
                <form id='unsubmitForm'
                    onSubmit={(e) => [
                        handleUnsubmitValues(),
                        handleSubmit(onSubmit)(e).catch((e) => {
                          console.log("e", e);
                        })]}    
                >
                    <CheckBoxIcon 
                        {...register('submitted')}
                        {...register('submittedBy')}
                        {...register('submittedDate')}
                    />
                    <label>{hasUser?.fullName}</label><br />
                    <label>{subDate}</label><br />
                    <Button color='warning' variant='contained'  form='unsubmitForm' type='submit'>Unsubmit</Button>
                </form>
                </>
            
        ) :
            <>
                <form id='submitForm'
                    onSubmit={(e) => [
                        handleSubmitValues(),
                        handleSubmit(onSubmit)(e).catch((e) => {
                          console.log("e", e);
                        })]}    
                >
                <CheckBoxOutlineBlankIcon 
                    {...register('submitted')}
                    {...register('submittedBy')}
                    {...register('submittedDate')}
                />
                </form>
                <Button color='primary' variant='contained'  form='submitForm' type='submit'>Submit Report</Button> 
            </>
        
                
        }
        <br />
        
     <br />
     </>

    )
}
  • Related