在功能组件中渲染数据之前如何等待FETCH?

时间:2020-03-27 14:28:42

标签: javascript reactjs react-admin

我正在尝试显示<Loading>组件,直到成功获取数据为止,
之后,我将显示Child组件。我不明白为什么状态没有更新...

我该如何处理?

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

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

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>);
};

3 个答案:

答案 0 :(得分:2)

我确实有老反应的经验
因此,我可以建议您使用这些技巧

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 &&时,初始化[]时始终为真,只有undefinednull并使用{{ 1}}并不是最好的方法,就好像数据库返回长度为0的defibs && defibs.length = 0数组一样,对您来说,应用将显示

答案 1 :(得分:0)

我认为问题在于您使用了错误的表达方式

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

您应将表达式更改为defibs.length <= 0,以明确要求<Loading />为空时呈现的defibs组件

答案 2 :(得分:0)

这更多地在于最初定义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
};

这应该为您的<Dashboard>工作逻辑提供正确的组件。