如何在useEffect-React加载的组件中渲染内容

how to render content in the component that is loaded by useEffect- React

我有一个要向其中获取数据的组件。正如预期的那样,组件首先呈现,然后是 useEffect。问题是这个 useEffect 获取了我需要在我的组件中呈现的数据。无论如何,我可以在 useEffect 将数据传播到 useState 之后让组件中的内容加载吗?

import React, { useEffect, useState } from 'react';
import Layout from '../components/global/layout/Layout';
import axios from 'axios';
import { Col, Row } from 'react-bootstrap';
import styles from '../components/page-css/menu.module.css';
import MenuItemHolder from '../components/menu-page/menuItemHolder/menuItemHolder';

const Menu = () => {
    const [ menuItems, setMenuItems ] = useState(false);

    useEffect(() => {
        const fetchData = async () => {
            const result = await axios('https://tahina-test.herokuapp.com/doggos');
            setMenuItems(result.data);
            
        };

        fetchData();
    }, []);

    return (
        <Layout textColor="white">
            <Col>
                <Row className={styles.menuHolder}>
                    <Col className={styles.menu} xs="11" md="8">
                        <h1>Menu</h1>
                        <Row>
                            {menuItems.records.map((item) => (
                                <MenuItemHolder name={item.Name} price={item.UnitPrice} />
                            ))}
                        </Row>
                    </Col>
                </Row>
            </Col>
        </Layout>
    );
};

export default Menu;

您可以预先初始化menuItems,这样访问menuItems.records就有效了。

const Menu = () => {
  const [menuItems, setMenuItems] = useState({ records: [] });

  useEffect(() => {
    //...
    fetchData();
  }, []);

  // records are empty until data fetch
  return (
    <>
      {menuItems.records.map((item) => {
        /*...*/
      })}
    </>
  );
};

export default Menu;

或者只使用 conditional rendering:

const Menu = () => {
  const [menuItems, setMenuItems] = useState();

  useEffect(() => {
    //...
    fetchData();
  }, []);

  // Conditional rendering
  return (
    <>
      // Same as menuItems && menuItems.records
      {menuItems?.records.map((item) => {
        /*...*/
      })}
    </>
  );
};

export default Menu;

添加 loading 状态以在 fetchData 从服务器获取数据时呈现加载元素。

import React, { useEffect, useState } from 'react';
import Layout from '../components/global/layout/Layout';
import axios from 'axios';
import { Col, Row } from 'react-bootstrap';
import styles from '../components/page-css/menu.module.css';
import MenuItemHolder from '../components/menu-page/menuItemHolder/menuItemHolder';

const Menu = () => {
    const [ loading, setLoading ] = useState(false);
    const [ menuItems, setMenuItems ] = useState({records: []});

    const fetchData = async () => {
        setLoading(true);
        const result = await axios('https://tahina-test.herokuapp.com/doggos');
        setLoading(false);
        setMenuItems(result.data);
    };

    useEffect(() => {
        fetchData();
    // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    return (
        <Layout textColor="white">
            <Col>
                <Row className={styles.menuHolder}>
                    {loading ? (
                       <Col className={styles.menu} xs="11" md="8">
                            Loading, please wait...
                       </Col>
                    ) : (
                        <Col className={styles.menu} xs="11" md="8">
                            <h1>Menu</h1>
                        
                            {menuItems.records.map((item, index) => (
                                <Row key={index}>
                                    <MenuItemHolder name={item.Name} price={item.UnitPrice} />
                                </Row>
                            ))}

                        </Col>
                    )}
                </Row>
            </Col>
        </Layout>
    );
};

export default Menu;

据我了解你的问题,你问的是如何仅在获取数据并且已使用此数据填充状态时呈现 MenuItemHolder 组件。

有两种方法可以实现:

#1 用空数组初始化 menuItems.records:

const [ menuItems, setMenuItems ] = useState({records: []});

这样在初始渲染时,menuItems.records.map([...]) 将 return 为空。

#2 根据条件渲染 MenuItemHolder 组件:

<Row>
    {menuItems && menuItems.records.map((item) => (
        <MenuItemHolder name={item.Name} price={item.UnitPrice} />
    ))}
</Row>

这将起作用,因为 menuItems 的初始值是 false