首页 > 解决方案 > React hooks async useEffect 加载数据库数据

问题描述

我在 React 中使用异步 useEffect 因为我需要执行数据库请求。然后,将此数据添加到我的react-charts-2

const [ plSnapShot, setPlSnapShot ] = useState({
   grossIncome: 0.00,
   opeExpenses: 0.00,
   nonOpeExpenses: 0.00,
   netIncome: 0.00,
   grossPotencialRent: 0.00,
   lastMonthIncome: 0.00
});

const [ thisMonthPayment, setThisMonthPayments ] = useState({
    labels: [],
    data: [],
    color: 'blue'
});


useEffect(() => {
    async function fetchData() {
        await axios.get(`${url.REQ_URL}/home/getUserFullName/${userID}`)
            .then(async (res) => {
                setUserFullName(res.data);

                await axios.get(`${url.REQ_URL}/home/getThisMonthPayments/${propertyID}`)
                    .then(async (resMonthPay) => {
                        let total = 0;
                        let obj = {
                            labels: [],
                            data: [],
                            color: 'blue'
                        };
                        const data = resMonthPay.data;
                        for(const d of data) {
                            obj.labels.push(helper.formatDate(new Date(d.date)));    
                            obj.data.push(d.amount);
                            total += d.amount;
                        }
                        setThisMonthPayments(obj);
                        setTotalEarnedMonth(parseFloat(total));

                        await axios.get(`${url.REQ_URL}/home/plSnapshot/${propertyID}`)
                            .then(async (resPL) => {
                                const data = resPL.data;
                                setPlSnapShot({
                                    grossIncome: parseFloat(data.GrossIncome || 0).toFixed(2),
                                    opeExpenses: parseFloat(data.OperatingExpenses || 0).toFixed(2),
                                    nonOpeExpenses: parseFloat(data.NonOperatingExpenses || 0).toFixed(2),
                                    netIncome: parseFloat(data.NetIncome || 0).toFixed(2),
                                    grossPotencialRent: parseFloat(data.GrossPotencialRent || 0).toFixed(2),
                                    lastMonthIncome: parseFloat(data.LastMonthIncome || 0).toFixed(2)
                                });
                            });
                    });
            });
    }
    fetchData();
}, [propertyID, userID]);

const pieChart = {
    chartData: {
        labels: ['Gross Income', 'Operating Expenses', 'Non Operating Expenses'],
        datasets: [{
            data: [plSnapShot.grossIncome, plSnapShot.opeExpenses, plSnapShot.nonOpeExpenses],
            backgroundColor: [
                ChartConfig.color.primary,
                ChartConfig.color.warning,
                ChartConfig.color.info
            ],
            hoverBackgroundColor: [
                ChartConfig.color.primary,
                ChartConfig.color.warning,
                ChartConfig.color.info
            ]
        }]
    }
};

const horizontalChart = {
    label: 'Last Month Income',
    labels: ['Gross Potencial Rent', 'Last Month Income'],
    chartdata: [plSnapShot.grossPotencialRent, plSnapShot.lastMonthIncome]
};

这是我如何在渲染/返回方法的代码中调用 Chart 组件的示例。

<TinyPieChart
   labels={pieChart.chartData.labels}
   datasets={pieChart.chartData.datasets}
   height={110}
   width={100}
/>

而我的饼图组件只是为了显示它

import React from 'react';
import { Pie } from 'react-chartjs-2';

// chart congig
import ChartConfig from '../../Constants/chart-config';

const options = {
    legend: {
        display: false,
        labels: {
            fontColor: ChartConfig.legendFontColor
        }
    }
};

const TinyPieChart = ({ labels, datasets, width, height }) => {
    const data = {
        labels,
        datasets
    };
    return (
        <Pie height={height} width={width} data={data} options={options} />
    );
}

export default TinyPieChart;

大多数情况下它工作得很好,但有时图表数据会很快加载并显示在屏幕上,然后它消失并且图表显示为空(无数据)。我是使用 useEffect 正确加载它还是应该使用其他方法?

谢谢。

标签: reactjs

解决方案


瞬间闪烁可能是由于图表数据在第一次渲染时为空。因此,根据您useEffect获取数据所需的时间,闪烁可能会带来真正的问题。

一种常见的解决方案是使用状态变量来指示正在加载数据,并且要么不显示任何内容来代替图表,要么显示某种已加载的数据。因此,您可以添加您在评论中建议的内容const [ loader, setLoader ] = useState(true)。然后,一旦加载数据,将其切换到false.

同时,在您的渲染函数中,您将执行以下操作:

...
...
{loader ? 
   <div>Loading....</div>
 :
   <TinyPieChart
    labels={pieChart.chartData.labels}
    datasets={pieChart.chartData.datasets}
    height={110}
    width={100}
   />

}

loader可以从真到假,反之亦然,这取决于对您来说更直观的意义。


推荐阅读