0

当我的图表组件由于其初始状态而呈现时出现错误,该状态在 API 响应之前是一个空数组。它会说类似这样Cannot read property '0' of undefined的内容,因为当组件加载时,它的初始状态是……一个空数组。所以我想知道是否有办法让组件仅在收到 API 响应后才呈现。

这是父组件:

function InformationPage({
    match: {
        params: { symbol },
    },
}) {

    const [chartData, setChartData] = useState([]); {/*Declaring state*/}

useEffect(() => {  {/*Fetching API response here to set state*/}
    axios
        .get(
            `https://finnhub.io/api/v1/stock/candle?symbol=${symbol}&resolution=15&from=1572651390&to=1602623478&token=xxxxxxxxx`
        )
        .then((res) => {
            console.log(res.data);
            setChartData(res.data);
        })
        .catch((err) => {
            console.log(err);
        });
}, [symbol]);

return (
    
        <Grid item container xs={12} sm={12} md={6} lg={8}>
            {chartData && <QuoteChart chartData={chartData} iex={iex} />}
        </Grid>
    
   );
}
export Default InformationPage;

这是子图表组件,基本上,当我从 axios 执行 fetch 请求时,它会返回一个数组,该数组将映射到chartRender对象中。我只需要在来自 axios 的 api 请求完成后才能找到一种方法来呈现组件,以免出现错误。任何帮助将不胜感激。

function QuoteChart(props) {
    const classes = useStyles();
    const { chartData } = props;

    const chartRender = chartData.map((chartConfig) => ({
        x: new Date(chartConfig?.t),
        y: [chartConfig?.o, chartConfig?.h, chartConfig?.l, chartConfig?.c],
    }));

    // const chartDataLog = console.log(chartData);
    const config = {
        series: [
            {
                data: [{ chartRender }],
            },
        ],
4

4 回答 4

5

更新:根据Finnhub API,它是您从 API 接收的对象,而不是数组。这意味着charData.length在我之前的答案中永远不会被评估,true并且子组件QuoteChart永远不会被渲染。

我建议进行以下更改。在您的父组件中,charData = null首先制作:

const [chartData, setChartData] = useState(null);

当 API 返回响应chartData并被分配一个值时,您的子组件可以被渲染:

{chartData && <QuoteChart chartData={chartData} iex={iex} />}

您要在子组件中呈现的图表需要以下输入:[{ x: date, y: [O,H,L,C] }]. 因为map()只能在数组上调用而chartData不是一个,所以您应该导航到所述对象内的数组之一,例如chartData.t

const chartRender = chartData.t.map((timestamp, index) => ({
    x: new Date(timestamp),
    y: [chartData.o[index], chartData.h[index], chartData.l[index], chartData.c[index]],
}));

最后,series.data需要一个数组,您不需要另外将它包装在一个对象中。所以这应该工作:

const config = {
    series: [{
        data: chartRender
    }]
};

您使用空数组进行初始化chartData,因此您的条件应如下所示:

{chartData.length && <QuoteChart chartData={chartData} iex={iex} />}

如果您希望 API 返回一个空列表,我建议将undefinedor设置null为 的初始值chartData

const [chartData, setChartData] = useState(null);

在这种情况下,您可以保持现状。

于 2020-10-15T13:06:50.967 回答
1

如果我没记错的话,你可以简单地使用 async/await 来解决你的问题。所以将 useEffect 行更改为

useEffect(async () => {  {/*Fetching API response here to set state*/}

进而

 await axios
    .get(
        `https://finnhub.io/api/v1/stock/candle?symbol=${symbol}&resolution=15&from=1572651390&to=1602623478&token=xxxxxxxxx`
    )

然后你的应用程序应该等待 axios 完成获取

于 2020-10-15T12:57:25.573 回答
0

最简单的方法需要对您的代码进行简单的小改动:

 {chartData.length && <QuoteChart chartData={chartData} iex={iex} />}

在研究了 finnhub 之后 - 我看到响应不是一个数组。我测试了这个网址:

https://finnhub.io/api/v1/stock/candle?symbol=AAPL&resolution=15&from=1572651390&to=1602623478&token=

响应是具有“c”属性的对象。您的代码应相应修改。对于上面的链接示例:

setChartData(res.data.c);
于 2020-10-15T12:58:28.520 回答
0

您需要将您的 axios 调用包装在异步函数wait

useEffect(() => {  {/*Fetching API response here to set state*/}
    
   const getInfo = async () => {
       await res = axios
        .get(
            `https://finnhub.io/api/v1/stock/candle?symbol=${symbol}&resolution=15&from=1572651390&to=1602623478&token=xxxxxxxxx`
        )
        console.log(res.data);
        setChartData(res.data);
   }

   getInfo()
}, [symbol]);
于 2020-10-15T13:08:10.577 回答