React中调用HTTP GET请求获取数据构建表格的问题求解
问题根因
React 中setState类的状态更新方法是异步批处理的,你在调用setServerData(response.data)后,当前代码块中的serverData依旧是初始的空数组,状态更新会等到当前同步代码执行完后才生效,因此紧接着调用fillRows()时遍历的是空数组,最终得到的rows自然也是空的。
解决方案
提供两种常用的修复方式:
方案1:直接将接口返回数据传入处理函数
无需等待状态更新,直接把接口拿到的响应数据作为参数传给fillRows,避免依赖还没更新的state:
import React, { useEffect, useState } from "react"; import axios from "axios"; import { DataGrid } from "@material-ui/data-grid"; function ServersTable() { const [loadingData, setLoadingData] = useState(true); const [serverData, setServerData] = useState([]); const [rows, setRows] = useState([]); const columns = [ { field: "hostname", headerName: "Hostname", width: 70 }, { field: "memory", headerName: "Memória", width: 70 }, { field: "vCpus", headerName: "vCPUs", width: 70 }, { field: "disk", headerName: "Disco", width: 70 }, { field: "ip", headerName: "IP", width: 70 }, ]; useEffect(() => { async function getData() { await axios .get("http://localhost:3333/servers") .then((response) => { const data = response.data setServerData(data); // 直接把拿到的新数据传给处理函数 fillRows(data); setLoadingData(false); }) } if (loadingData) { getData(); } }, []); // 接收传入的数据源做处理,不依赖state function fillRows(data) { let rowArray = []; for (let count = 0; count < data.length; count++) { let row; row = { id: count, hostname: data[count].hostname, memory: data[count].configuracao.memoryProvisioned + " GB", vCpus: data[count].configuracao.cpuProvisioned + " vCPUs", disk: data[count].configuracao.totalDiskGB + " GB", ip: data[count].ip, }; rowArray.push(row); } setRows(rowArray); } return ( <> {loadingData ? ( <p>Loading Please Wait...</p> ) : ( <DataGrid rows={rows} columns={columns} checkboxSelection /> )} </> ); } export default ServersTable;
方案2:通过useEffect监听serverData变化触发处理
如果需要依赖serverData状态做后续处理,可以新增一个副作用监听serverData的变化,等它更新后再执行rows的生成逻辑:
// 只需要修改两处,其余代码不变 useEffect(() => { async function getData() { await axios .get("http://localhost:3333/servers") .then((response) => { setServerData(response.data); setLoadingData(false); // 删掉原来的fillRows调用 }) } if (loadingData) { getData(); } }, []); // 新增这个useEffect,监听serverData变化 useEffect(() => { fillRows() }, [serverData])
优化建议
rows属于可以通过serverData计算得到的派生状态,不需要单独维护state,可以用useMemo减少冗余状态:
const rows = useMemo(() => { return serverData.map((item, index) => ({ id: index, hostname: item.hostname, memory: item.configuracao.memoryProvisioned + " GB", vCpus: item.configuracao.cpuProvisioned + " vCPUs", disk: item.configuracao.totalDiskGB + " GB", ip: item.ip, })) }, [serverData])
内容的提问来源于stack exchange,提问作者Rafael Picolo
相关产品推荐
相关产品推荐

