typescriptreact-hooksreact-tsx

How to render the HTML after a stateVariable set in React with TypeScript


I'm trying to render a HTML block after a state variable succesfully setted. For this purpose, in below, I defined my state variables and my functions to set them a value.

    const formService:FormService=new FormService();
    
    const [appointmentDate, setAppointmentDate] = useState<AppointmentDate>();
    const [formattedDate, setFormattedDate ]=useState<string>()
    const [formattedTime, setFormattedTime ]=useState<string>()
    const [formattedTime20MinutesBefore, setFormattedTime20MinutesBefore] = useState<string>()


    useEffect(()=>{
        init();
    },[])

    const init = async ()=>{
        await getAppointmentData();
        await organizeTheDates();
    }

    const getAppointmentData = async ()=>{
        const appointmentDateVar= await formService.getAppointmentPageInformation(3);
        setAppointmentDate(appointmentDateVar);
    }

    const organizeTheDates = async ()=>{
        if (appointmentDate) {
            // set the time and date variables
            const date:Date =(new Date(appointmentDate.dateTime));
            setFormattedDate(`${date.getDate().toString().padStart(2, '0')}/${(date.getMonth() + 1).toString().padStart(2, '0')}/${date.getFullYear()}`)
            setFormattedTime(`${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`)

            const twentyMinutesBefore = new Date(date.getTime() - 20 * 60000);
            setFormattedTime20MinutesBefore(`${twentyMinutesBefore.getHours().toString().padStart(2, '0')}:${twentyMinutesBefore.getMinutes().toString().padStart(2, '0')}`);

        }
    }

Now, I want to render my code after the values set. For this, I wrote a if-else block. But when I run it, it is getting stuck at the else page.

if(formattedDate != undefined && formattedTime != undefined ){
        return ( ** my page ** ) } 
}else {
        return <div>loading</div>
    }

But when I save the code again in IDE, react re-renders the page and this time it enters to the if block.

As I understand, problem is related to useState variables being asynchronus, is there is a way to make this work? Thank you very much.

UPDATE

I changed this parts like this according to Quentin's answer, thank you.

const init = async ()=>{

        await organizeTheDates(await getAppointmentData());
    }

    const getAppointmentData = async ()=>{
        const appointmentDateVar=await formService.getAppointmentPageInformation(3);
        setAppointmentDate(appointmentDateVar)
        return appointmentDateVar;
    }

Solution

  • setAppointmentDate stores a value in the state. It doesn’t change appointmentDate (at least not until the component rerenders) so you can’t read it from there in organizeTheDates.

    Instead, return a value from getAppointmentData then have the init function pass it to organizeTheDates.