【问题标题】:How to wait for FETCH before rendering DATA in Functional Component?如何在功能组件中渲染 DATA 之前等待 FETCH?
【发布时间】:2020-03-27 14:28:42
【问题描述】:

我正在尝试显示一个<Loading> 组件,直到 DATA 获取成功,
之后我显示一个子组件。我不明白为什么状态没有更新...

我该如何处理?

我正在使用react-admin,但我猜这并不重要。
我有一个<Dashboard>,它应该将defibs (Array) 传递给<DefibsCard>

当我在<DefibsCard> 中记录defibs 时,我有一个空数组。谢谢!

const Dashboard = () => {
  const dataProvider = useDataProvider();
  const [loading, setLoading] = useState(true);
  const [defibs, setDefibs] = useState([]);

  const fetchDefibs = () => {
    dataProvider.getList('defibrillateurs', {
      filters: {}, sort: {field: 'id', order: 'ASC'}, pagination: {page: 1, perPage: 10}
    }).then((response) => {
      setDefibs(response.defibs);
      setLoading(false);
    })
  }

  useEffect(() => {
    fetchDefibs();
    console.log(loading)
  }, [])

  const classes = useStyles();

  return (!defibs 
    ? <Loading />
    : <div className={classes.flex}>
        <div className={classes.leftCol}>
          <div className={classes.flexColumn}>
            // ...
            <div className={classes.flex}>
              <DefibsCard defibs={defibs}/> // Child component
              <AlertsCard />
            </div>
          </div>
        </div>
        // ...
      </div>);
};

【问题讨论】:

    标签: javascript reactjs react-admin


    【解决方案1】:

    我确实有旧反应的经验
    所以我可以建议你这些chanfes

    useEffect(() => {
        setLoading(true); // here 
        fetchDefibs();
        console.log(loading)
    }, [])
    

    然后

    const fetchDefibs = () => {
        dataProvider.getList('defibrillateurs', {
            filters: {},
            sort: {field: 'id', order: 'ASC'},
            pagination: { page: 1, perPage: 10 }
        }).then((response) => {
            setLoading(false);   // here 
            setDefibs(response.defibs)
            setLoading(false);
        }).catch( e =>         setLoading(false);)
    
    }
    

    然后

    return(
        {!loading ? <Loading />
        :
        <div className={classes.flex}>
            <div className={classes.leftCol}>
                <div className={classes.flexColumn}>
                    <Card>
                        <CardHeader title="Welcome to the administration" />
                        <CardContent>Lorem ipsum sic dolor amet...</CardContent>
                    </Card>
                ......
       }
    

    当您使用{ defibs &amp;&amp; 时,它将始终为真,因为您已对其进行了初始化[],只有当它是undefinednull 时才会为假,并且使用defibs &amp;&amp; defibs.length = 0 不是最好的方法,好像数据库返回数组长度为 0 [] 然后你的应用程序将显示加载

    【讨论】:

    • 你可以使用dataProvider.getList(...).then(...).finally(() => setLoading(false));
    • @JaimeNoelAlvarezLuna 太完美了。谢谢分享
    【解决方案2】:

    我认为问题是你使用了错误的表达方式

    !defibs 始终返回false,无论defibs 是空数组还是加载的数组。

    您应该将表达式更改为defibs.length &lt;= 0 以明确要求&lt;Loading /&gt; 组件在defibs 为空时呈现

    【讨论】:

      【解决方案3】:

      这更多取决于您最初如何定义 defibs 变量。
      让我们更仔细地看一下...

      const Dashboard = () => {
        // This is where the bug is...
      - const [defibs, setDefibs] = useState([]);
        // !defibs === `false`
        // ![] or ![1,2,3,4] === `false`
      
        // Update this line as follows
      + const [defibs, setDefibs] = useState(null);
        // Initially !defibs, since !null === true, thus <Loading> is rendered
        // After the `useEffect`, state is actually updated...
        // And !defibs is false, since ![] === false, the <DefibsCard> is rendered
      
        //...the rest looks fine
      };
      

      这应该让您的 &lt;Dashboard&gt; 工作逻辑能够呈现正确的组件。

      【讨论】:

        【解决方案4】:

        对于功能组件我觉得最好的是useeffect

        import { useEffect, useState } from 'react';
        function FetchEmployeesByQuery({ query }) {
          const [employees, setEmployees] = useState([]);
          useEffect(() => {
            async function fetchEmployees() {
              const response = await fetch(
                `/employees?q=${encodeURIComponent(query)}`
              );
              const fetchedEmployees = await response.json(response);
              setEmployees(fetchedEmployees);
            }
            fetchEmployees();
          }, [query]);
          return (
            <div>
              {employees.map(name => <div>{name}</div>)}
            </div>
          );
        }
        

        来源: 5. Fetching data

        【讨论】:

          猜你喜欢
          • 2020-06-17
          • 2021-12-03
          • 1970-01-01
          • 2020-09-13
          • 2017-01-14
          • 2020-02-11
          • 2023-04-01
          • 2020-12-09
          • 2022-12-03
          相关资源
          最近更新 更多