如何让我的页面等待钩子获取所有数据?
How make my page wait till the hook got all data?
我正在构建一个基于 TypeScript 模板的 React 应用程序,我的一个页面在挂钩完成加载之前正在加载。
我试过 makings async await 但它是一个钩子,效果不佳。
我如何构建一些东西来等待我的挂钩完成,然后将其加载到页面上?
我的页面:
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>
这是我的钩子(注意文件是.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}
}
我认为解决方案是在渲染组件上添加条件渲染。在您的自定义挂钩中,您可以再添加一个加载状态,然后您可以基于该状态渲染您的组件。
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
}
那么你可以使用如下加载
const { topEventsSelected ,loading} = useGetTopEvents(3);
return(
<div className="d-flex flex-column min-vh-100">
<NavBar/>
{loading ? ...loading : your render login}
)
最好的方法是有条件地呈现 return 中的元素。
const [data, setData] = useState(null);
在您的 return 方法中
return ({
data : <>Your component</> ? <LoadingState />
})
故障排除 我意识到代码将数据分配给方法 setEventValues(parsedEventos);
上的参数所花费的时间更长,因此,由于它是 multi-thread,它开始 运行 organizeEvents()
在完成之前将数据分配给 setEventValues。
通过函数参数发送数据来解决这个问题:organizeEvents(parsedEventos)
然后处理信息并将其保存在常量中。
我还将 organizeEvents 更改为异步,从而避免损坏
这里是钩子的最终代码:
export function useGetTopEvents(quant: number){
const [topEvents, setTopEvents] = useState<Evento[]>([]);
const [topEventsSelected, setTopEventsSelected] = useState<Evento[]>([]);
const [loading, setLoading] = useState(true)
async function organizeEvents(eventValues: Evento[]){
//organazing events by confirmed users
let topAllEvents:Evento[] = <Evento[]>[];
await eventValues.forEach(element =>{
if(element.confirmNumb > 0){
topAllEvents.push(element)
}
})
await topAllEvents.sort((a,b) => b.confirmNumb - a.confirmNumb)
await setTopEvents(topAllEvents)
//organazing events by quantity selected
let topSelected = topAllEvents;
await topSelected.sort((a,b) => b.confirmNumb - a.confirmNumb).slice(0,3);
await setTopEventsSelected(topSelected);
await setLoading(false)
}
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)
organizeEvents(parsedEventos);
})
}, [quant])
return{topEvents, topEventsSelected, loading}
}
我正在构建一个基于 TypeScript 模板的 React 应用程序,我的一个页面在挂钩完成加载之前正在加载。
我试过 makings async await 但它是一个钩子,效果不佳。
我如何构建一些东西来等待我的挂钩完成,然后将其加载到页面上?
我的页面:
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>
这是我的钩子(注意文件是.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}
}
我认为解决方案是在渲染组件上添加条件渲染。在您的自定义挂钩中,您可以再添加一个加载状态,然后您可以基于该状态渲染您的组件。
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
}
那么你可以使用如下加载
const { topEventsSelected ,loading} = useGetTopEvents(3);
return(
<div className="d-flex flex-column min-vh-100">
<NavBar/>
{loading ? ...loading : your render login}
)
最好的方法是有条件地呈现 return 中的元素。
const [data, setData] = useState(null);
在您的 return 方法中
return ({
data : <>Your component</> ? <LoadingState />
})
故障排除 我意识到代码将数据分配给方法 setEventValues(parsedEventos);
上的参数所花费的时间更长,因此,由于它是 multi-thread,它开始 运行 organizeEvents()
在完成之前将数据分配给 setEventValues。
通过函数参数发送数据来解决这个问题:organizeEvents(parsedEventos)
然后处理信息并将其保存在常量中。
我还将 organizeEvents 更改为异步,从而避免损坏
这里是钩子的最终代码:
export function useGetTopEvents(quant: number){
const [topEvents, setTopEvents] = useState<Evento[]>([]);
const [topEventsSelected, setTopEventsSelected] = useState<Evento[]>([]);
const [loading, setLoading] = useState(true)
async function organizeEvents(eventValues: Evento[]){
//organazing events by confirmed users
let topAllEvents:Evento[] = <Evento[]>[];
await eventValues.forEach(element =>{
if(element.confirmNumb > 0){
topAllEvents.push(element)
}
})
await topAllEvents.sort((a,b) => b.confirmNumb - a.confirmNumb)
await setTopEvents(topAllEvents)
//organazing events by quantity selected
let topSelected = topAllEvents;
await topSelected.sort((a,b) => b.confirmNumb - a.confirmNumb).slice(0,3);
await setTopEventsSelected(topSelected);
await setLoading(false)
}
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)
organizeEvents(parsedEventos);
})
}, [quant])
return{topEvents, topEventsSelected, loading}
}