Home > Net >  How make my page wait till the hook got all data?
How make my page wait till the hook got all data?

Time:05-19

I'm building a react app based on TypeScript template and one of my pages is loading before the hook completes the load.

I tried makings async await but it is a hook, didn't work well.

How can I build something to wait my hook completes and then load it on the page?

My page:

export function Home(){


    const { topEventsSelected } = useGetTopEvents(3);

    

    return(
        <div className="d-flex flex-column min-vh-100">
            <NavBar/>
                
                <div className="container">
                    <div className="row mt-4 mb-4 gap">
                        <div className="col-md">
                            <div className="card">
                                <div className="sizingt d-flex card-body flex-column align-items-center sizingt">
                                    <h1>TOP Eventos</h1>
                                    {topEventsSelected.map((eventoInfo)=>
                                        moment(eventoInfo.dataFinal).isBefore() || eventoInfo.cancelado === 'Y' ? 
                                            (
                                                console.log()
                                            ):(
                                                <BlueCard props={eventoInfo}/>
                                            )
                                        
                                    )}
                                </div>
                            </div>
                        </div>
                        

Here is my hook (note that the file is .ts):

export function useGetTopEvents(quant: number){
    const [eventValues, setEventValues] = useState<Evento[]>([]);
    const [topEvents, setTopEvents] = useState<Evento[]>([]);
    const [topEventsSelected, setTopEventsSelected] = useState<Evento[]>([]);
    
    function organizeEvents(){
        //organazing events by confirmed users
        let topAllEvents = []
        for(let organizer of eventValues){
            if(organizer.confirmNumb > 0){
                topAllEvents.push(organizer)
            }
        }
        topAllEvents.sort((a,b) => b.confirmNumb - a.confirmNumb)
        setTopEvents(topAllEvents)

        //organazing events by quantity selected
        let topSelected = topAllEvents;
        topSelected.sort((a,b) => b.confirmNumb - a.confirmNumb).slice(0,3);
        setTopEventsSelected(topSelected);
    }

    useEffect(() =>{
        const eventRef = database.ref(`eventos`);

        eventRef.once('value', evento => {
            //console.log(evento.val())
            const databaseEventos = evento.val();

            const firebaseEvent: FirebaseEventos = databaseEventos ?? {};
            
            const parsedEventos = Object.entries(firebaseEvent).map(([key, value])=>{
                return{
                    id: key,
                    autorID: value.authorID,
                    autorNome: value.authorName,
                    categoria: value.category,
                    dataInicio: value.startDate,
                    dataFinal: value.endDate,
                    titulo: value.title,
                    cancelado: value.canceled,
                    confirmNumb: Object.entries(value.confirmados ?? {}).length
                }
            }) 
            
            //console.log(parsedEventos)
            
            setEventValues(parsedEventos);

            organizeEvents();
        })

    }, [quant])

    return{topEvents, topEventsSelected}
}

CodePudding user response:

I think the solution would be to add a conditional render on your render component. In you custom hook you could add one more state for loading, and then you can render your component based on that.

export function useGetTopEvents(quant: number) {

  const [loading,set] = useState<Boolean>(true)

  function organizeEvents() {
    //organazing events by confirmed users
    ...your function
  }

  useEffect(() => {
      ...
      //console.log(parsedEventos)

      setEventValues(parsedEventos);
      setLoading(false) // set the state to false
      organizeEvents();
    });
  }, [quant]);

  return {topEvents, topEventsSelected, loading};

  // also return the loading state so you could use it with your custom hook
}

Then you could use the loading as follow

const { topEventsSelected ,loading} = useGetTopEvents(3);


      return(
        <div className="d-flex flex-column min-vh-100">
            <NavBar/>
                
               {loading ? ...loading : your render login}
)

CodePudding user response:

Best way to do will be conditional rendering of the elements in your return.

const [data, setData] = useState(null);

Inside your return method

   return ({
data : <>Your component</> ? <LoadingState />
})
  • Related