仅在API请求完成后才渲染组件React钩子

时间:2020-10-15 12:53:39

标签: javascript reactjs rest axios react-hooks

由于其初始状态(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执行获取请求时,它返回一个数组,该数组将映射到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 个答案:

答案 0 :(得分:2)

更新:根据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返回一个空列表,建议您将undefinednull设置为chartData的初始值:

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

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

答案 1 :(得分: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完成提取

答案 2 :(得分: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);

答案 3 :(得分: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]);
相关问题