如何延迟 React 从渲染 child 组件直到 parent 组件完成获取?

How to delay React from rendering child component until parent component finish fetching?

我有一个 parent 组件,它从 webAPI 获取并将 return 一组人。 我还有一个 child 组件,它假设从 parent 接收道具,其中道具是从 fetch

获得的

我遇到的问题是,在获取完成之前,反应似乎呈现了 child 组件。 这是我的代码:

import React from "react";
import { Person} from "./Components";

export function Body({departmentId}){

const [peopleArray,setPeopleArray] = React.useState([]);

    React.useEffect(
        () => {
          const getPeopleArr = async () => {
          
            const response = await
             fetch(`https://xxxx`);           
             const data = await response.json();  
             setPeopleArray(data);       
              
          };
          getPeopleArr();
        }, []);

    return(
        <div>
            <Person name={peopleArray[0].personalDetails.name} position={peopleArray[0].department.name}/>      
        </div>
    );
}

从上面可以看出,peopleArray 最初是一个空数组。并且反应会给我错误“未捕获的类型错误:无法读取未定义的属性(读取'personalDetails')” 如果我删除代码<Person name={peopleArray[0].personalDetails.name} position={peopleArray[0].department.name}/> 稍等一下,等它抓取下来,然后快速粘贴代码,就成功显示了Person组件。

我试图在 child 组件中添加 SetTimeOut 并尝试将其延迟几秒钟,方法是:

setTimeout(() => {
}, "2000")

但这似乎对解决问题没有帮助。

能否请您建议我可以做些什么来延迟 child 组件在获取完成之前渲染? 谢谢

编辑: 我能想到的一件事是为我想传递给 child 的每个道具创建多个 useState(s),例如

const [name,SetName] = data[0].personalDetails.name;
...

<Person name = {name}>

但是如果我有 20 个道具要传递,那么我必须创建 20 个 useState(s)

编辑:?工作...谢谢大家:D

只要引入一个像“loaded”这样的状态,然后有条件地渲染你的子组件:

loaded && <ChildComponent />

你的情况:

import React from "react";
import { Person} from "./Components";

export function Body({departmentId}){

const [peopleArray,setPeopleArray] = React.useState([]);
const [loaded, setLoaded] = React.useState(false);

    React.useEffect(
        () => {
          const getPeopleArr = async () => {
          
            const response = await
             fetch(`https://xxxx`);           
             const data = await response.json();  
             setPeopleArray(data);       
              
          };
          await getPeopleArr();
          setLoaded(true);
        }, []);

    return(
        <div>
            {loaded && <Person name={peopleArray[0].personalDetails.name} position={peopleArray[0].department.name}/>}  
        </div>
    );
}

快速修复,只是检查数组的长度:

return peopleArray.length ? <Person name={peopleArray[0].personalDetails.name} position={peopleArray[0].department.name}/> : <></>

虽然没有考虑fetch结果为空数组的情况

您可以添加“?”在 peopleArray[0] 之后以避免错误:

<Person name={peopleArray[0]?.personalDetails.name} position={peopleArray[0]?.department.name}/>

或者你可以使用条件渲染:

<div>
 {peopleArray[0] ? <Person name={peopleArray[0].personalDetails.name} 
 position={peopleArray[0].department.name}/> : null }    
</div>
 

你应该先检查变量是否不为空:

{peopleArray.length && <Person name={peopleArray[0]?.personalDetails.name} position={peopleArray[0]?.department.name}/> }

有几种方法可以解决这个问题。

最简单的是使用可选链接。像这样:

<Person name={peopleArray[0]?.personalDetails?.name} position={peopleArray[0]?.department?.name}/>

如果 peopleArray[0] 未定义,则不会呈现任何内容

另一个解决方案是使用长度:

peopleArray.length > 0 && <Person name={peopleArray[0].personalDetails.name} position={peopleArray[0].department.name}/>

第三个是引入一个loading状态,可以默认为true,可以在fetch promise resolved后改成false