React 使用 useEffect 异步加载数据

时间:2021-03-22 15:40:03

标签: javascript reactjs

我有一个父组件,其中有一个子组件,它当前异步加载数据:

<Parent> 
  <AsyncChild data={props.data} />
  <Child />
</Parent>

在我的 AsyncChild 组件中:

const processDataAsynchronously = data => {
      // do stuff with a huge chunk of data
} 

export default function AsyncChild(props) {

    const data = props.data;
    const [dataLoaded, setDataLoaded] = useState(false);
    const [myData, setMyData] = useState({});

    useEffect(() => {
        let mounted = true;
        processDataAsynchronously(data);
        .then(data => {
            if(mounted) {
                setMyData(data);
                setDataLoaded(true);
            }
        });  
        return () => {
            mounted = false;
        }   
       }, [data])

    const getComponentData = () => {
        if(dataLoaded && !myData){ 
            // if data has loaded and is empty return empty
            return <span />
        } else if (!myData && !dataLoaded)  { 
            // if data is empty and loading is not complete - return loading component
            return <Loader />;
        } else {
            return (
                // return style data
            )
        }      
    }

    return (
        <div>
            {getComponentData()}
        </div>  
    )
} 

我想要做的是加载 <Child />,当 <AsyncChild /> 异步处理它的数据时,在 <Child /> 组件上方显示一个加载器。但是,当前加载程序不显示,并且两个子组件一起显示。我该如何正确执行此操作?

1 个答案:

答案 0 :(得分:3)

你可以像这样在父组件中添加一个状态:

import { useState } from 'react';


export default function App () {
 
 [isLoading, setLoading] = useState(false);

 return (
  <Parent> 
   <AsyncChild data={props.data} setLoading={setLoading}/>
   {isLoading && <Loader />}
   <Child />
  </Parent>
 )
}

然后在 AsyncChild 中,您可以在 isLoading 中设置 useEffect

useEffect(() => {
    setLoading(true); // <----- START LOADING
    let mounted = true;
    processDataAsynchronously(data);
    .then(data => {
        if(mounted) {
            setMyData(data);
            setDataLoaded(true);
        }
        setLoading(false); // <----- END LOADING
    });  
    return () => {
        mounted = false;
    }   
   }, [data])