React数组map渲染表格时如何调用API获取股票价格并展示
你当前的写法有两个核心问题:
- JSX里直接定义的匿名函数不会被React自动执行,不会返回任何内容到视图
- fetch是异步请求,渲染同步执行的情况下不可能直接拿到异步返回值,同时每次组件重渲染都会重复触发请求,会严重浪费接口配额、造成页面卡顿
正确实现方案
实现思路
- 给持仓数组的每一项新增
currentPrice、loading、error字段,用来存储请求返回的当前价格、加载状态、报错信息 - 用
useEffect在组件挂载时统一触发所有股票的价格请求,请求完成后更新状态触发重渲染 - 渲染时直接读取状态里的对应字段即可
import { useState, useEffect } from 'react' const StockTable = () => { const [account, setAccount] = useState([ { "Symbol": 'AAPL', "Shares": 1, "TotalCost": 130, "currentPrice": null, "loading": false, "error": null }, { "Symbol": 'TSLA', "Shares": 1, "TotalCost": 1500, "currentPrice": null, "loading": false, "error": null }, ]) useEffect(() => { // 遍历所有持仓股票拉取价格 account.forEach(stock => { // 已经有价格的可以跳过,避免重复请求 if (stock.currentPrice) return // 更新加载状态 setAccount(prev => prev.map(item => item.Symbol === stock.Symbol ? {...item, loading: true} : item )) fetch(`https://finnhub.io/api/v1/quote?symbol=${stock.Symbol}&token=12345678910`) .then(res => res.json()) .then(data => { // 请求成功更新价格 setAccount(prev => prev.map(item => item.Symbol === stock.Symbol ? { ...item, loading: false, currentPrice: data.c } : item )) }) .catch(err => { // 请求失败更新报错 setAccount(prev => prev.map(item => item.Symbol === stock.Symbol ? { ...item, loading: false, error: '获取失败' } : item )) }) }) }, []) // 空依赖保证只在组件挂载时执行一次,需要定时刷新可以自己加定时器 return ( <table> <tbody> {account.map((stocks) => { const {Symbol , Shares, TotalCost, currentPrice, loading, error} = stocks; return ( <tr key={Symbol}> {/* 注意加key属性,React列表必须 */} <td>{Symbol}</td> <td>{Shares}</td> <td>${TotalCost}</td> <td> {loading ? '加载中...' : error ? error : currentPrice ? `$${currentPrice.toFixed(2)}` : '-'} </td> {/* 可自行扩展盈亏对比列 */} <td> {currentPrice ? `$${((currentPrice * Shares) - TotalCost).toFixed(2)}` : '-'} </td> </tr> ) })} </tbody> </table> ) } export default StockTable
注意事项
- 不要把第三方API的token直接写在前端代码里,很容易被爬取滥用,建议自己搭建后端服务代理所有接口请求,把token存在后端
- 如果持仓股票数量较多,可以加请求限流,避免短时间内触发过多请求被接口限流
- 需要实时价格可以在useEffect里加定时器,定时拉取最新价格
内容的提问来源于stack exchange,提问作者user16645351
相关产品推荐
相关产品推荐

