基于API调用显示图表数据

问题描述 投票:1回答:2

我正在尝试学习使用商店的反应。我想做的是拥有2个组件(一个主组件和一个子组件),我想调用API用于主要组件中的数据,并将此数据传递给子组件,然后在react-chartjs-2组件中呈现此数据。

这是我的主要组件(Home.tsx),它调用UserData的API(我从后端正确地以数组[]的形式接收数据。

import React, { useEffect, useState } from "react";
import { History } from "history";
import { connect } from "react-redux";
import { ApplicationState } from "../../store";
import { actionCreators, reducer } from "../../store/auth";
import axios from 'axios';
import 'antd/dist/antd.css'
import { Card, Button } from 'antd';
import BalanceChart from "./child-components/BalanceChart";

type HomeProps = ReturnType<typeof reducer>
    & typeof actionCreators
    & { readonly history: History };

const Home: React.FC<HomeProps> = ({
                                         id,
                                         historicalBalanceValues
                                     }) => {
    const [balanceValue, setBalanceValue] = React.useState([]);

    const getUserRequest = async () => {
        let response = await axios({
            url: `https://localhost:44340/api/users/${id}`,
            method: 'get'
        });
        return response.data;
    };
    useEffect(() => {
        id = sessionStorage.getItem("userId");
        getUserRequest()
            .then(data => {
                setBalanceValue(data.item.balanceValue);

                if (!!data.item.historicalBalances){
                    historicalBalanceValues = data.item.historicalBalances.map(r => r.balanceValue);
                }
            });
    });
    return (
        <div >
            <h1 className='home-header'>Savings</h1>
            <div className='card-container'>
                <Card style={{ width: 400, marginLeft: '75px' }} title={'Total balance'}>
                    <div className='balance-container'>
                        <div className='balance-value'>{balanceValue}</div>
                        <Button className='goal-button' type='primary' shape='round'>Add goal</Button>
                    </div>
                </Card>
                <Card style={{ width: 400, marginLeft: '75px'}} title={'Balance trend'}>
                    <BalanceChart chartData={historicalBalanceValues}></BalanceChart>
                </Card>
            </div>
        </div>
    );
};
const mapStateToProps = (state: ApplicationState) => ({
    id: state.auth.id
});

export default connect(mapStateToProps, actionCreators)(Home);

这是我的第二个组件,我要在其中使用从Home组件传递来的数据来显示折线图。

import React, { Component } from 'react';
import { Line } from 'react-chartjs-2';
import axios from 'axios';
import PasswordInput from "../../Login/child-components/PasswordInput";

type BalanceChartState = {
    balanceChartData: []
}
let chartOptionsData = {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [{
        label: 'Label',
        data: this.props.chartData,
        backgroundColor: [
            'rgba(255, 99, 132, 0.2)'
        ],
        borderColor: [
            'rgba(255, 99, 132, 1)',
        ],
        borderWidth: 1
    }]
};

export class BalanceChart extends Component<{chartData: any}, BalanceChartState> {

    componentDidMount() {
        this.setState({balanceChartData: this.props.chartData})
    }

    render() {
        const { balanceChartData } = this.state;
        return (balanceChartData && balanceChartData.length) ?
         <Line data={chartOptionsData}></Line> :  <Line data={[0]}></Line>
    }
}

export default BalanceChart;

问题是,我从一个组件传递到另一组件的数据是'undefined'。我认为对API的数据调用发生在组件渲染之后,但是我不知道该如何实现。组件渲染后,我想传递数据。我想知道什么是达到此目的的良好做法。谢谢

reactjs typescript react-redux chart.js
2个回答
0
投票

哦,所以我向父(Home)组件添加了条件渲染。渲染现在看起来像这样:

<Card style={{ width: 400, marginLeft: '75px'}} title={'Balance trend'}>
{
   !!historicalBalanceValues ?
   <BalanceChart chartData={historicalBalanceValues}></BalanceChart> : <Spin/>
}
</Card>

所以现在我有无限的预加载器(historicalBalanceValues是未定义的),甚至艰难的API调用也向我返回了一个其值不表示BalanceChart组件的数组。我认为条件渲染仅以某种方式检查一次。我该如何实现以应对变化?


0
投票

我找到了解决方案,并且确实将两个组件都更改为类组件。我使用道具在它们之间传递数据,并使用State存储来自Home组件内部后端的数据。感谢您的帮助!

© www.soinside.com 2019 - 2024. All rights reserved.