【问题标题】:how to render content in the component that is loaded by useEffect- React如何在useEffect-React加载的组件中渲染内容
【发布时间】:2020-10-29 01:08:18
【问题描述】:

我有一个要从中获取数据的组件。正如预期的那样,组件首先呈现,然后是 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;

【问题讨论】:

    标签: reactjs use-effect use-state


    【解决方案1】:

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

    有两种方法可以实现:

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

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

    这样在初始渲染时,menuItems.records.map([...]) 将返回一个空值。

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

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

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

    【讨论】:

      【解决方案2】:

      您可以预先初始化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;
      

      【讨论】:

        【解决方案3】:

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

        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;
        

        【讨论】:

          猜你喜欢
          • 2021-05-26
          • 2017-07-14
          • 1970-01-01
          • 2020-01-06
          • 2021-02-17
          • 2020-01-20
          • 2021-02-21
          • 2021-05-18
          • 1970-01-01
          相关资源
          最近更新 更多