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 />
})