条件渲染不等待获取完成
Conditional Rendering not waiting for Fetch to Complete
在应用程序中,我从 Firebase/Firestore 获取数据,将其解析为接口并将 object 添加到状态数组。之后我想渲染它。但是反应不会渲染数组。我已经评论了代码,你可以看到我认为它应该做什么。
const Tab1: React.FC = () => {
let spiceArray: singleSpice[] = [];
interface singleSpice {
spice: string,
grams: number,
}
useEffect(() => {
//fetch the data --> Works well
async function loadData() {
const data = await getCollections();
// Add the Data to the Spicearray --> Works
data.forEach((e: any) => spiceArray.push(e));
}
// Trigger Function onComponentMount
loadData();
// This function will never log "Worked" even tho the loadData is Async
if(spiceArray.length > 0){
console.log("Worked")
}
})
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
//Transfer the spiceArray to the next Child as Props --> Works
<CustomTab1 spices={spiceArray}/>
<ExploreContainer name="Tab 1 page" />
<IonButton onClick={() => console.log(spiceArray.length)}> Test me</IonButton>
</IonContent>
</IonPage>
);
};
export default Tab1;
Child
//Interface for Props
interface Props {
spices: Spice[];
}
//Interface to get access to inner Attributes of the SpiceObjectArray
interface Spice {
spice: string;
grams: number;
}
const CustomTab1: React.FC<Props> = ({spices}: Props) => {
return (
<IonList>
//Conditional Render
{spices.length > 0 && spices.map(entry => <IonItem id={entry.spice}>{entry.spice}</IonItem>)}
<IonButton onClick={() => console.log(spices)}>Test</IonButton>
</IonList>
);
};
export default CustomTab1;
疯狂的事情是。现在,当我按 F5 时,会显示香料的 IonicApp none。但是,当我更改 CustomTab1-Component 上 IoNButton 内的文本并保存简单的更改时,香料将被渲染。但是如果我按 F5 刷新应用程序,一切都消失了 again.How 我可以让应用程序等到 API 传送数据吗?
spiceArray 不是状态,无法重新呈现您的子组件。
将您的变量更改为状态
当变量改变时,React 不会重新渲染。你说你正在将获取的对象传递给“状态数组”但是 spiceArray
不是一个反应状态。在功能组件中,状态是用 useState 声明的。
当您的页面最初加载时,没有数据,您的想法是正确的,在尝试映射 over/render 之前先检查是否有任何数据。但是为了让组件重新渲染并因此重新检查 spicesArray 中是否有任何内容,您必须使用状态并更改状态。
const [spiceArray, setSpiceArray] = useState<singleSpice[] | null>(null)
useEffect(() => {
//fetch the data --> Works well
async function loadData() {
const data = await getCollections();
// Add the Data to the Spicearray --> Works
setSpiceArray(data)
}
// Trigger Function onComponentMount
loadData();
// This function will never log "Worked" even tho the loadData is Async
if (spiceArray.length > 0) {
console.log("Worked");
}
}, []);
您的代码应如下所示
并将子组件渲染逻辑更改为:
{spices && spices.map(entry => <IonItem id={entry.spice}>{entry.spice}</IonItem>)}
请记住其他几件事:
- 如果你希望 useEffect 只在挂载时 运行(这通常是在获取数据时的情况),你需要一个空的依赖数组。
- 控制台记录 spiceArray 或检查 spiceArray.length 是否不为 0 在 useEffect 中仍然不起作用,因为反应中的状态更新是异步的/为下一个渲染更新状态的请求。因此,更改不会立即反映/观察到
您不用等待 loadData();
吗?
然后继续if(spiceArray.length > 0){
在应用程序中,我从 Firebase/Firestore 获取数据,将其解析为接口并将 object 添加到状态数组。之后我想渲染它。但是反应不会渲染数组。我已经评论了代码,你可以看到我认为它应该做什么。
const Tab1: React.FC = () => {
let spiceArray: singleSpice[] = [];
interface singleSpice {
spice: string,
grams: number,
}
useEffect(() => {
//fetch the data --> Works well
async function loadData() {
const data = await getCollections();
// Add the Data to the Spicearray --> Works
data.forEach((e: any) => spiceArray.push(e));
}
// Trigger Function onComponentMount
loadData();
// This function will never log "Worked" even tho the loadData is Async
if(spiceArray.length > 0){
console.log("Worked")
}
})
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonTitle>Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Tab 1</IonTitle>
</IonToolbar>
</IonHeader>
//Transfer the spiceArray to the next Child as Props --> Works
<CustomTab1 spices={spiceArray}/>
<ExploreContainer name="Tab 1 page" />
<IonButton onClick={() => console.log(spiceArray.length)}> Test me</IonButton>
</IonContent>
</IonPage>
);
};
export default Tab1;
Child
//Interface for Props
interface Props {
spices: Spice[];
}
//Interface to get access to inner Attributes of the SpiceObjectArray
interface Spice {
spice: string;
grams: number;
}
const CustomTab1: React.FC<Props> = ({spices}: Props) => {
return (
<IonList>
//Conditional Render
{spices.length > 0 && spices.map(entry => <IonItem id={entry.spice}>{entry.spice}</IonItem>)}
<IonButton onClick={() => console.log(spices)}>Test</IonButton>
</IonList>
);
};
export default CustomTab1;
疯狂的事情是。现在,当我按 F5 时,会显示香料的 IonicApp none。但是,当我更改 CustomTab1-Component 上 IoNButton 内的文本并保存简单的更改时,香料将被渲染。但是如果我按 F5 刷新应用程序,一切都消失了 again.How 我可以让应用程序等到 API 传送数据吗?
spiceArray 不是状态,无法重新呈现您的子组件。
将您的变量更改为状态
当变量改变时,React 不会重新渲染。你说你正在将获取的对象传递给“状态数组”但是 spiceArray
不是一个反应状态。在功能组件中,状态是用 useState 声明的。
当您的页面最初加载时,没有数据,您的想法是正确的,在尝试映射 over/render 之前先检查是否有任何数据。但是为了让组件重新渲染并因此重新检查 spicesArray 中是否有任何内容,您必须使用状态并更改状态。
const [spiceArray, setSpiceArray] = useState<singleSpice[] | null>(null)
useEffect(() => {
//fetch the data --> Works well
async function loadData() {
const data = await getCollections();
// Add the Data to the Spicearray --> Works
setSpiceArray(data)
}
// Trigger Function onComponentMount
loadData();
// This function will never log "Worked" even tho the loadData is Async
if (spiceArray.length > 0) {
console.log("Worked");
}
}, []);
您的代码应如下所示 并将子组件渲染逻辑更改为:
{spices && spices.map(entry => <IonItem id={entry.spice}>{entry.spice}</IonItem>)}
请记住其他几件事:
- 如果你希望 useEffect 只在挂载时 运行(这通常是在获取数据时的情况),你需要一个空的依赖数组。
- 控制台记录 spiceArray 或检查 spiceArray.length 是否不为 0 在 useEffect 中仍然不起作用,因为反应中的状态更新是异步的/为下一个渲染更新状态的请求。因此,更改不会立即反映/观察到
您不用等待 loadData();
吗?
然后继续if(spiceArray.length > 0){