【问题标题】:Rendering a component only after API request is finished React hooks仅在 API 请求完成后渲染组件 React hooks
【发布时间】:2021-01-29 23:10:37
【问题描述】:

当我的图表组件由于其初始状态(在 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 }],
            },
        ],

【问题讨论】:

    标签: javascript reactjs rest axios react-hooks


    【解决方案1】:

    更新:根据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);
    

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

    【讨论】:

    • 我使用了chartData.length,但是当我从子组件 console.log chartData 时,什么也没有出现。我停止收到错误,但组件也没有呈现。
    • @Pacholoamit 当您从 API 收到响应时,console.log(res.data); 的输出是什么?
    • 我会设置一个codepen,你可以帮我看看。这真的让我很困惑。几分钟后我会在这里评论它。有什么办法可以和你聊天,如果可以的话?我是一名女程序员,如果我遇到麻烦可以找人帮忙,我将不胜感激。但是,如果您不喜欢这种方式,那么回答这个问题就可以了。我现在将从我的存储库中设置 codepen。
    • 请查看我的更新答案,希望对您有所帮助。拥有 Codepen 的链接总是一个好主意。
    • 您好,很抱歉回复晚了。这是codesandbox 在代码和框中它说Cannot read property 'map' of undefined 但是在我的本地主机中它说Unhandled Rejection (Error): Please provide [Open, High, Low and Close] values in valid format. Read more https://apexcharts.com/docs/series/#candlestick 我做了一个console.log 并且在地图功能的输出方面一切都很好,但是我得到一个顶点图错误,说格式不合适。让我知道你的想法。
    【解决方案2】:

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

     {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);
    

    【讨论】:

    • 我使用了 chartData.length 但是当我从子组件中 console.log chartData 时,什么也没有出现。我停止收到错误,但组件也没有呈现。
    • 如果子组件什么都不渲染,这意味着 chartData.length 为 false - 这意味着它是空数组、对象或数字...您确定 chartData 是一个数组吗?
    • 这是我在 console.log 原样登录 api response 时得到的结果。
    • 基本上你应该检查 res.data.s 的状态——要么是“ok”要么是“no_data”。然后你应该使用你感兴趣的数据。您应该阅读有关 finnhub api 的更多信息:finnhub.io/docs/api#stock-candles
    • 这是顶点图表,我正在使用的库。 Finnhub 一直 100% 正常工作,我相信正如您所测试的那样。 api 返回 o、h、l 和 c 数组。这就是为什么我刚刚做了 res.data,因为我将访问图表组件中的 o、h、l 和 c 数组,但在初始渲染时它一直说错误消息“无法读取未定义的属性 [0]”。我基本上只需要在 api 请求完成后渲染图表,这样我就可以将 o、h、l 和 c 数组传递给负责图表中数据的子组件中的 map 函数。感谢您帮助初级开发人员。
    【解决方案3】:

    您需要将您的 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]);
    

    【讨论】:

      【解决方案4】:

      如果我没记错的话,您可以简单地使用 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 完成获取

      【讨论】:

      • 您不能将异步函数传递给useEffect
      猜你喜欢
      • 1970-01-01
      • 2019-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-07
      相关资源
      最近更新 更多