Как ждать FETCH перед рендерингом данных в функциональном компоненте? - PullRequest
1 голос
/ 27 марта 2020

Я пытаюсь отобразить компонент <Loading>, пока выборка данных не будет успешной, после чего я отображаю дочерний компонент. Я не понимаю, почему состояние не обновляется ...

Как я могу справиться с этим?

Я использую 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>);
};

Ответы [ 4 ]

2 голосов
/ 27 марта 2020

У меня есть опыт работы со старым Так что я могу предложить вам эти 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 &&, это всегда будет верно, как вы Инициализируйте это [], это будет только ложь, если это undefined или null, и использование defibs && defibs.length = 0 не лучший способ, как если бы массив возвращаемых данных базы данных с длиной 0 [], тогда ваше приложение покажет загрузку

0 голосов
/ 30 марта 2020

Спасибо, ребята, за ваши ответы. Сейчас работает

0 голосов
/ 28 марта 2020

Это больше связано с тем, как вы изначально определяете переменную 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> рабочему логику c для визуализации нужного компонента.

0 голосов
/ 27 марта 2020

Я думаю, проблема в том, что вы используете неправильное выражение

!defibs всегда возвращайте false независимо от того, defibs пустой массив или загруженный массив.

Вы должны изменить выражение для defibs.length <= 0 для явного запроса <Loading /> компонента, который будет отображаться, когда defibs пусто

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...