【问题标题】:Fetching data with hook takes too long time使用钩子获取数据需要很长时间
【发布时间】:2020-07-21 07:53:54
【问题描述】:

我正在尝试获取并映射一个包含 350 个对象元素的数组。我决定使用 Hook 和 useEffect,在映射完成后重新渲染我的 dataTable 组件。不幸的是,整个过程需要大量时间,并且会使页面无响应。 1-2 分钟后,表格出现,几秒钟后消失。之后页面仍然没有响应。有人可以解释为什么会发生这种情况,并给我一些解决方法吗?我将感激不尽。 代码如下:

const Employees = (props) => {
const [developers, setDevelopers] = useState([]);

useEffect(() => {
    fetchData();
});

const columns = [
    {
        name: "Emloyee",
        selector: "name",
        sortable: true,
    },
    {
        name: "Team ",
        selector: "team",
        sortable: true,
    },
    {
        name: "Email ",
        selector: "email",
        sortable: true,
    },
];

const fetchData = () => {
    axios.get("http://localhost:3128/employees", {
        headers: {
            'Access-Control-Allow-Origin': '*',
        }
    })
        .then((response) => {
            mapData(response.data.developers);
            console.log("I am here!");
        })
        .catch((e) => console.log(e));
};

const mapData = (jsonData) => {
    jsonData.forEach((x) => {
        let newDeveloper = {
            name: x.userId,
            team: x.team,
            email: x.userId + "@mail.com",
        };
        setDevelopers((developers) => [...developers, newDeveloper]);
    });
};

return <DataTable title="Employees" columns={columns} data={developers}/>;

};

【问题讨论】:

  • 网络响应时间长吗?我无法想象映射约 350 个对象需要花费大量时间/精力。你做了什么调试来看看什么是慢的?为什么不只映射 json 数据并设置一次状态,而不是一次为每个元素设置状态?
  • 说实话,我对webs app的调试并不精通,看来,重渲染和hook状态更新有些麻烦。
  • 可能是F12 打开浏览器的开发工具,您应该会看到一个标有“网络”的选项卡。从这里您应该能够看到请求需要多长时间。如果您跳过 axios 调用并在通用“随机”数据中映射,更新是否仍然很慢?你需要弄清楚哪一部分是慢的,然后深入研究那个位。
  • “为什么不只映射 json 数据并设置一次状态,而不是一次为每个元素设置状态?”那成功了!谢谢

标签: javascript reactjs optimization web-applications react-hooks


【解决方案1】:

useEffect 没有依赖数组将在每个渲染上运行,所以在你的情况下,你会陷入无限循环,导致页面变得无响应

解决方案:

const fetchData = useCallback(() => {
    axios.get("http://localhost:3128/employees", {
        headers: {
            'Access-Control-Allow-Origin': '*',
        }
    })
        .then((response) => {
            mapData(response.data.developers);
            console.log("I am here!");
        })
        .catch((e) => console.log(e));
},[]);
const mapData = useCallback((jsonData) => {
    jsonData.forEach((x) => {
        let newDeveloper = {
            name: x.userId,
            team: x.team,
            email: x.userId + "@kuehne-nagel.com",
        };
        setDevelopers((developers) => [...developers, newDeveloper]);
    });
},[]);
useEffect(() => {
    fetchData();
},[fetchData]); // pass dependency array here in useEffect

【讨论】:

  • 之后出现错误:“ReferenceError: Cannot access 'fetchData' before initialization”
  • 在定义 fetchDatamapData 之后转移 useEffect
  • 解决了,但仍然存在相同的性能问题:/
  • 没有一个
  • 如果您的 http 请求需要很长时间才能完成,请检查您的网络选项卡。
【解决方案2】:

感谢@DrewReese 和@SarthakAggarwal,我找到了解决方案:

const Employees = (props) => {
const [developers, setDevelopers] = useState([]);


const columns = [
    {
        name: "Emloyee",
        selector: "name",
        sortable: true,
    },
    {
        name: "Team ",
        selector: "team",
        sortable: true,
    },
    {
        name: "Email ",
        selector: "email",
        sortable: true,
    },
];

const fetchData = useCallback(() => {
    axios.get("http://localhost:3128/employees", {
        headers: {
            'Access-Control-Allow-Origin': '*',
        }
    })
        .then((response) => {
            mapData(response.data.developers);
            console.log("I am here!");
        })
        .catch((e) => console.log(e));
}, []);

const mapData = (jsonData) => {
  let table = [];
    jsonData.forEach((x) => {
        let newDeveloper = {
            name: x.userId,
            team: x.team,
            email: x.userId + "@mail.com",
        };
        table = [...table,newDeveloper];
        //setDevelopers((developers) => [...developers, newDeveloper]);
    });
  setDevelopers((developers) => table);
};

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


return <DataTable title="Employees" columns={columns} data={developers}/>;

};

非常感谢!

【讨论】:

    猜你喜欢
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-31
    • 2020-10-03
    相关资源
    最近更新 更多