【问题标题】:Wait for API data before render react hooks在渲染反应钩子之前等待 API 数据
【发布时间】:2021-04-27 02:14:57
【问题描述】:

我做了两个 API 调用。来自getAllCampaign api 的数据呈现但对于loadStats 似乎 React 继续构建一个没有数据的表,从而引发错误 未捕获的类型错误:无法读取未定义的属性“数据” 这就是我正在做的事情。

coreapihelpers:

export const getAllCampaign = () => {
    return fetch(`https://api.truepush.com/api/v1/listCampaign/1`, {
        method: "GET",
        headers: {
            Authorization: `$TOKEN`,
            "Content-Type": "application/json",
        },
    })
    .then(response => {
        return response.json()
    })
    .catch(err => console.log(err))
}

export const loadStats = async () => {
    const ids = await getAllCampaign()

    const data = Promise.all(
        ids.data.map(async (i) => await (await fetch(`https://api.truepush.com/api/v1/campaignStats/${i.campaignId}`, {
            method: "GET",
            headers: {
                Authorization: ``$TOKEN``,
                "Content-Type": "application/json"
            }
        })).json())
    )
    return data
};

allData 控制台输出延迟

完整代码:

import React, {useState, useEffect} from 'react';
import {getAllCampaign, loadStats} from "../helpers/coreapihelpers";

const TableRow = () => {

    const [campaigns, setCampaigns] = useState([]);
    const [stats, setStats] = useState([]);

    const loadAllCampaigns = () => {
        getAllCampaign()
            .then(data => { setCampaigns(data.data) })
            .catch(err => { console.log(err) });
    };

    const loadAllStats = () => {
        loadStats()
            .then(data => { setStats(data) })
            .catch(err => { console.log(err) });
    }

    useEffect(() => {
       loadAllCampaigns();
       loadAllStats();
    }, [])

    const allData = campaigns.map ? campaigns.map((campaign, i) => ({
        ...campaign,
        ...stats[i],
    }))
        : <h1>API LIMIT EXCEEDS</h1>

    return (
        <div className="container">
            <div className="row">
                <div className="col-xs-12">
                    {allData.map ? allData.map((campaigns, index) => (
                        <div className="table-responsive" data-pattern="priority-columns">
                            <table className="table table-bordered table-hover">
                                <thead>
                                <tr>
                                    <th>Sr. No</th>
                                    <th>Campaign Id</th>
                                    <th>Campaign Name</th>
                                    <th>Campaign Status</th>
                                    <th>Reach</th>
                                    <th>Sent</th>
                                    <th>Delivered</th>
                                    <th>Views</th>
                                    <th>Clicks</th>
                                    <th>Unsubscribers</th>
                                </tr>
                                </thead>
                                <tbody>
                                <tr key={index}>
                                    <td>{index + 1}</td>
                                    <td>{campaigns.campaignId}</td>
                                    <td>{campaigns.campaignTitle}</td>
                                    <td>{campaigns.campaignStatus}</td>
                                    <td>{campaigns.data.Reach}</td>
                                    <td>{campaigns.data.Sent}</td>
                                    <td>{campaigns.data.Delivered}</td>
                                    <td>{campaigns.data.Views}</td>
                                    <td>{campaigns.data.Clicks}</td>
                                    <td>{campaigns.data.Unsubscribers}</td>
                                </tr>
                                </tbody>
                            </table>
                        </div>)) : <h1>API Limit Exceeds / API Token Broken</h1>}
                    </div>
                 </div>
            </div>
            );
        }

export default TableRow;

【问题讨论】:

    标签: javascript reactjs react-hooks components


    【解决方案1】:

    我认为问题在于您应该检查状态 campaigns 是否已填充,而不是 allDataallData 是一个变量,而不是实际状态。实际状态应用于条件渲染。试试这个:

    替换这个:

    allData.map ? allData.map((campaigns, index)
    

    有了这个:

    campaigns ? allData.map((campaigns, index)
    

    但是,您应该为状态创建一个包含活动和统计数据的对象,因为您打算将它们用作相应的项目。或者,您的数据库查询应该将它们作为一个项目返回,并有一段时间的连接。

    试试这个作为客户端解决方案:

    const [stateObj, setObj] = useState([]);
    const campaigns = [];
    const stats = [];
    
    const loadAllState = async () => {
        try {
           campaigns = await getAllCampaign();
        } catch (err) {
           console.log(err)
        }
    
        try {
           stats = await loadStats();
        } catch (err) {
           console.log(err)
        }
    
        setObj(campaigns.map((campaign, i) => ({
           ...campaign,
           ...stats[i],
      })))
    };
    
    useEffect(() => {
       loadAllState();
    }, [])
    

    然后:

    stateObj ? stateObj.map((campaigns, index)
    

    【讨论】:

    • allData 变量包含营销活动的数据以及统计数据...而营销活动状态包含营销活动的数据,而统计数据仅包含统计数据@silencedogood
    • 我知道。这就是为什么我在答案末尾添加了警告。您需要更改数据的结构,方法是将所有数据存储在一个状态对象中,或者返回一个连接的数据集。您不能使用普通变量有条件地呈现状态。它必须与状态有关。 @prashantpadadune
    • 所以我应该从 allData 中设置值?
    • @prashantpadadune 更新了可能的解决方案。
    • 问题是我不明白如何处理这个问题,我是编程新手 :( 我也没有使用任何后端,它是我用来获取数据的 truepush api @silencedogood
    【解决方案2】:

    您应该查看 allData 是否已这样定义

     {allData ? allData.map((campaigns, index) => .......}
    

    【讨论】:

    • 它的所有数据变量都包含广告系列的数据以及统计数据...
    猜你喜欢
    • 1970-01-01
    • 2019-12-31
    • 2021-04-05
    • 2021-08-23
    • 2016-04-30
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 2019-05-30
    相关资源
    最近更新 更多