在反应材料表组件中获取异步数据

Posted

技术标签:

【中文标题】在反应材料表组件中获取异步数据【英文标题】:Getting async data in a react material table component 【发布时间】:2020-09-04 04:09:04 【问题描述】:

我正在使用 Firebase 构建一个小型 React 应用程序来托管和存储数据,我正在使用 Material-Table 来显示数据。问题是当我尝试将数据加载到表中时出现此错误:

Error: Objects are not valid as a React child (found: [object Promise]). If you meant to 
    render a collection of children, use an array instead.
    in EditTable (at App.js:12)
    in div (at App.js:10)
    in App (at src/index.js:10)
    in StrictMode (at src/index.js:9)

这是表格的代码:

import React from 'react';
import MaterialTable from 'material-table';
import  forwardRef  from 'react';

import AddBox from '@material-ui/icons/AddBox';
import ArrowDownward from '@material-ui/icons/ArrowDownward';
import Check from '@material-ui/icons/Check';
import ChevronLeft from '@material-ui/icons/ChevronLeft';
import ChevronRight from '@material-ui/icons/ChevronRight';
import Clear from '@material-ui/icons/Clear';
import DeleteOutline from '@material-ui/icons/DeleteOutline';
import Edit from '@material-ui/icons/Edit';
import FilterList from '@material-ui/icons/FilterList';
import FirstPage from '@material-ui/icons/FirstPage';
import LastPage from '@material-ui/icons/LastPage';
import Remove from '@material-ui/icons/Remove';
import SaveAlt from '@material-ui/icons/SaveAlt';
import Search from '@material-ui/icons/Search';
import ViewColumn from '@material-ui/icons/ViewColumn';
import getShotjes from './shotjesDao'

const tableIcons = 
    Add: forwardRef((props, ref) => <AddBox ...props ref=ref />),
    Check: forwardRef((props, ref) => <Check ...props ref=ref />),
    Clear: forwardRef((props, ref) => <Clear ...props ref=ref />),
    Delete: forwardRef((props, ref) => <DeleteOutline ...props ref=ref />),
    DetailPanel: forwardRef((props, ref) => <ChevronRight ...props ref=ref />),
    Edit: forwardRef((props, ref) => <Edit ...props ref=ref />),
    Export: forwardRef((props, ref) => <SaveAlt ...props ref=ref />),
    Filter: forwardRef((props, ref) => <FilterList ...props ref=ref />),
    FirstPage: forwardRef((props, ref) => <FirstPage ...props ref=ref />),
    LastPage: forwardRef((props, ref) => <LastPage ...props ref=ref />),
    NextPage: forwardRef((props, ref) => <ChevronRight ...props ref=ref />),
    PreviousPage: forwardRef((props, ref) => <ChevronLeft ...props ref=ref />),
    ResetSearch: forwardRef((props, ref) => <Clear ...props ref=ref />),
    Search: forwardRef((props, ref) => <Search ...props ref=ref />),
    SortArrow: forwardRef((props, ref) => <ArrowDownward ...props ref=ref />),
    ThirdStateCheck: forwardRef((props, ref) => <Remove ...props ref=ref />),
    ViewColumn: forwardRef((props, ref) => <ViewColumn ...props ref=ref />)
;

export default async function EditTable() 

    const [state, setState] = React.useState(
        columns: [
             title: 'ID', field: 'ID' , type: 'numeric' ,
             title: 'uitdeler', field: 'Uitdeler' ,
             title: 'ontvanger', field: 'Ontvanger' ,
             title: 'Uitgedeeld', field: 'Uitgedeeld', lookup:  1: true, 0: false ,,
             title: 'datum', field: 'Datum',
            ,
        ],
        data: getShotjes(),
    );


    return (
        <MaterialTable
            title="Editable Example"
            columns=state.columns
            data=this.state.data
            icons=tableIcons
        />
    );

这是我的简单 dao 文件减去配置:

import firebase from 'firebase/app'

export async function getShotjes() 
        try 
            require("firebase/firestore");

            const firebaseConfig = 
            ;

            if (!firebase.apps.length) 
                firebase.initializeApp(firebaseConfig);
            

            var db = firebase.firestore();
            const snapshot = await db.collection('shotjes').get();
            return snapshot.docs.map(doc => doc.data());

        
        catch (e) 
            console.log(e);

        


编辑:

因此,添加一个 useEffect 挂钩并拆分数据和列状态可以消除所有错误。虽然我仍然没有看到表中出现任何数据。我的 Table 组件现在看起来像这样:

export default function EditTable() 

var [state, setState] = React.useState(
    columns: [
         title: 'ID', field: 'id' , type: 'numeric' ,
         title: 'Uitdeler', field: 'uitdeler' ,
         title: 'Ontvanger', field: 'ontvanger' ,
         title: 'Uitgedeeld', field: 'uitgedeeld', lookup:  1: true, 0: false ,,
         title: 'Datum', field: 'datum',
        ,
    ],
);

var [data, setData] = React.useState([]);

console.log(JSON.stringify(data));

useEffect(() => 
    (async () => 
        const result = await getShotjes();
        console.log(result);
        setData(result);
    )();
, []);


return (
    <MaterialTable
        title="Editable Example"
        columns=state.columns
        data=data.data
        icons=tableIcons
    />
);

【问题讨论】:

useEffect 挂钩中调用getShotjes(),而不是返回数据,而是使用setData(data) 来设置它(在您的状态下分离列和数据)。 谢谢,我试试 【参考方案1】:

这就是我修复它的方法,我还添加了添加删除数据的功能。

EditTable.js:

export default function EditTable() 

var [state, setState] = React.useState(
    columns: [
         title: 'ID', field: 'id', type: 'numeric', editable: false,
         title: 'Uitdeler', field: 'uitdeler' ,
         title: 'Ontvanger', field: 'ontvanger' ,
         title: 'Datum', field: 'datum', type: 'date',
    ],
);

var [data, setData] = React.useState([]);
const [isLoading,setIsLoading] = useState(false);

useEffect(() => 
    // By moving this function inside the effect, we can clearly see the values it uses.
    setIsLoading(true);
    async function fetchProduct() 
        if (!firebase.apps.length) 
            firebase.initializeApp(firebaseConfig);
        

        setData(await getShotjes());
        setIsLoading(false);

    

    fetchProduct();
, []);

const handleCreateShotje = async (shotje)  => 
    setIsLoading(true);
    await addShotje(shotje).then(async () => 
        setData(await getShotjes());
    );
    setIsLoading(false);
;
const handleDeleteShotje = async (id)  => 
    setIsLoading(true);
    await removeShotje(id).then(async () => 
        setIsLoading(true);
        setTimeout(async function () 
            setData(await getShotjes());
            
        , 400);
        setIsLoading(false);
    );

;

return (
    <MaterialTable

        title="Shotjes"
        columns=state.columns
        data=(data)
        icons=tableIcons
        isLoading=isLoading
        editable=
            isEditable: rowData => rowData.name === "id", // make id not editable
            onRowAdd: (newData) => handleCreateShotje(newData),
            onRowDelete: (oldData) => handleDeleteShotje(oldData.id)

        
    />

);

【讨论】:

以上是关于在反应材料表组件中获取异步数据的主要内容,如果未能解决你的问题,请参考以下文章

反应材料 ui 表不会拉伸填充

当子点击事件命中时反应从父组件获取数据

从材料 ui 处理自动完成组件的更改

如何在具有角度嵌套数据组的材料表中显示拆分标题

在功能性反应组件中获取未定义的道具

Angular 材料 2 在组件之间共享反应形式