嘿,
我有一个 PortfolioPage 组件(下面的代码)通过组件 useEffect 内的 axios 库向我的 api 调用 GET 请求。
请求后 它使用 setPortfolio 钩子设置投资组合属性。
然后,我将投资组合传递给 HoldingsChart 组件(添加的组件代码)。 当我尝试使用在 HoldingsChart 组件内部传递的投资组合道具时,它告诉我投资组合是一个空对象。
我相信这与 setState 的异步方式有关 但是另一个组件(AssetChart)确实得到了正确呈现,所以我找不到问题。 真的很想得到一些帮助。
作品集页面组件代码:
const PortfolioPage = ({match}) =>{
const user = useContext(UserContext)
const [portfolio, setPortfolio] = useState({})
const portfolioId = match.params.portfolioId
useEffect(() => {
// getPortfolio(user.token, portfolioId, setPortfolio)
const getPortfolio = async () => {
const domain = "http://127.0.0.1:8000/api"
await axios.get(domain + `/portfolios/${portfolioId}`,{
headers:{
'Authorization': `Token ${user.token}`
}
})
.then((res) => {
setPortfolio(res.data)
})
}
getPortfolio()
},[])
return (
<React.Fragment>
<AssetChart records={portfolio.records} />
<HoldingsChart portfolio={portfolio}/>
</React.Fragment>
)
}
HoldingsChart 组件代码:
const HoldingChart = ({portfolio}) =>{
const holdings = portfolio.holdings
const totalValue = portfolio.total_value
const [data, setData] = useState([])
useEffect(() =>{
const holdingsPercentages = []
holdings.forEach(holding => holdingsPercentages.push({value: holding.total_value / totalValue}))
setData(holdingsPercentages)
},[])
const renderCustomizedLabel = ({
cx, cy, midAngle, innerRadius, outerRadius, percent, index,
}) => {
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
const x = cx + radius * Math.cos(-midAngle * RADIAN);
const y = cy + radius * Math.sin(-midAngle * RADIAN);
return (
<text x={x} y={y} fill="black" fontSize="10" textAnchor={x > cx ? 'start' : 'end'} dominantBaseline="central">
{`${data[index].asset} ${(percent * 100).toFixed(0)}%`}
</text>
);
};
return (
<PieChart width={350} height={350}>
<Pie
data={data}
cx={175}
cy={100}
labelLine={false}
label={renderCustomizedLabel}
innerRadius={40}
outerRadius={80}
fill="#8884d8"
dataKey="value"
>
{
data.map((entry, index) => <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />)
}
<Tooltip/>
</Pie>
</PieChart>
);
}
错误:
TypeError: Cannot read property 'forEach' of undefined
(anonymous function)
C:/Users/David/Desktop/Long-Term/longterm/src/components/assets-comps/HoldingsChart.js:15
12 | const [data, setData] = useState([])
13 | useEffect(() =>{
14 | const holdingsPercentages = []
> 15 | holdings.forEach(holding => holdingsPercentages.push({value: holding.total_value / totalValue}))
| ^ 16 | setData(holdingsPercentages)
17 | },[])
18 |
谢谢
答案 0 :(得分:1)
在遍历 holdings
之前添加一个空检查
if(holdings && holdings.length) {
holdings.forEach
}
或
holdings && holdings.length && holdings.forEach
或
holdings?.forEach
原因:
您的持有图表组件甚至在收到 api 响应之前就已呈现。 (在收到api响应时会再次重新渲染,因此添加空检查即可解决问题。
更简单更好的解决方案
添加变量 isResponseLoading 以在 api 调用正在进行时显示加载器并呈现您的 HoldingsChart 组件,仅当 api 响应可用时。
{isResponseLoading && <Spinner />
{!isResponseLoading && portfolio?.length && <HoldingsChart portfolio={portfolio}/> }