React table 不渲染从 API 返回的数据,除非我创建虚拟数据

React table not rendering data returned from an API unless I create dummy data

我有一个基本的 React Table,当我从 API.

返回的数据构建 object 数组时,它不渲染数据

我正在将 API 中的数据重构到它自己的 object 中,将 object 推入一个数组,然后将其设置为状态(使用 useState), table 然后应该渲染。

            let tableData = []
            pendingKYC.forEach(async (address) => {
                let userData = await contract.retrieveOwnerInfo(address);
                let refactored = {
                    address: address,
                    firstName: userData.firstName,
                    lastName: userData.lastName,
                }
                tableData.push(refactored);
            });
           setPendingKYCRequestsTableData(tableData);

但是它没有渲染。 Headers 而已,其余为空白。我发现如果我创建一个包含完全相同数据的 objects 的“虚拟”数组,并将 that 推送到状态,它工作正常。

const testData = [{
                address: "0x8e5acD67EFDdB1fb8c54491C8A0EB6f3CFD77ae3",
                firstName: "Killua",
                lastName: "Zoldyck",
            },
            {
                address: "0x2b71400D0Eb16b0C878aa12d4cF9FbE03fFcF36f",
                firstName: "Gon",
                lastName: "Freecs",
            }];

            setPendingKYCRequestsTableData(testData);

到处使用 console.logs 并在 Chrome 控制台中检查它,我能看到的唯一区别是它似乎采用不同的格式。

不起作用的那个(第一个)是[]类型的数组。 确实有效的(我的虚拟数据)是 [{...}, {...}] 类型的数组。

这到底有什么区别?有人可以阐明我可能做错了什么吗?

不做 code-dump 但这是我的 Table 组件

const PendingKYCTable = ({pendingKYCRequestsTableData, approveButtonHandler}) =>{
 

    
   useEffect(()=>{
    console.log("PendingKYCTable parent component useEffect", pendingKYCRequestsTableData);
   });

    console.log("PendingKYCTable rendered", pendingKYCRequestsTableData);

    const columns = React.useMemo(
        () => [
        {
          Header: "Pending KYC Requests",
          columns: [
            {
                Header: "Address",
                accessor: "address"
            },
            {
                Header: "First Name",
                accessor: "firstName"
            },
            {
                Header: "Last Name",
                accessor: "lastName"
            },
           
          ]
        }
      ]);

      const Table = ({ columns, data }) => {
        const {
          getTableProps,
          getTableBodyProps,
          headerGroups,
          rows,
          prepareRow
        } = useTable({
          columns,
          data
        });
        console.log("Table component data var", data);
        useEffect (() => {
            console.log("Table useEffect",data);
        });
      
        return (
          <table {...getTableProps()}>
            <thead>
              {headerGroups.map(headerGroup => (
                <tr {...headerGroup.getHeaderGroupProps()}>
                  {headerGroup.headers.map(column => (
                    <th {...column.getHeaderProps()}>{column.render("Header")}</th>
                  ))}
                </tr>
              ))}
            </thead>
            <tbody {...getTableBodyProps()}>
              {rows.map((row, i) => {
                prepareRow(row);
                return (
                  <tr {...row.getRowProps()}>
                    {row.cells.map(cell => {
                      return <td {...cell.getCellProps()}>{cell.render("Cell")}</td>;
                    })}
                  </tr>
                );
              })}
            </tbody>
          </table>
        );
      };

      return(
        <div>{pendingKYCRequestsTableData && <Table columns={columns} data={pendingKYCRequestsTableData} getTrProps={approveButtonHandler}/>}</div>

    );
};

export default PendingKYCTable;

我从 parent 组件调用它,传递包含如下数据的状态:

<div><PendingKYCTable pendingKYCRequestsTableData={pendingKYCRequestsTableData} approveButtonHandler={approveButtonHandler}/></div>

我在其他地方发现了一些非常有用的建议,所以我将展示它是如何解决的。显然你不能对异步请求使用 forEach 循环。常规的 for 循环工作得很好。我用这个替换了我的 forEach 循环:

 for (var i = 0; i < pendingKYC.length; i++){
        const address = pendingKYC[i];
        let userData = await contract.retrieveOwnerInfo(address);
        let refactored = {
            address: address,
            firstName: userData.firstName,
            lastName: userData.lastName,
        }
        tableData.push(refactored);
    }