React函数组件中子组件向父组件传值出现无限循环该如何解决?
问题根因
你出现无限循环的核心原因是React函数组件的执行机制和API调用的触发逻辑不符合规范:
- 你提供的
CallAPI函数组件代码没有展示callgcmpapi的触发时机,大概率是直接在组件顶层调用了这个函数,没有用useEffect包裹控制执行时机。函数组件每次渲染都会从头执行所有顶层代码,调用接口后更新组件内部state,state更新又会触发组件重新渲染,重新渲染又会再次调用接口、更新state,最终形成死循环。 - 类组件中你是把API调用放在了
componentDidMount这类生命周期钩子中,只会在组件挂载后执行一次,所以不会出现循环问题,确实是函数组件的生命周期处理逻辑写错了。 - 额外注意:你当前的
CallAPI函数组件没有声明接收props参数,子组件传给它的age属性目前无法被CallAPI内部获取,如果需要使用这个参数,要把组件定义改成const CallAPI = (props) => {或者解构写法const CallAPI = ({age}) => {。
解决办法
修改CallAPI.js的代码,用useEffect包裹API调用逻辑,控制它只在依赖项变化的时候执行即可:
import { useState, useEffect } from 'react'; import Axios from 'axios'; // 需要接收props就加上参数 const CallAPI = (props) => { const [DPID, setText] = useState(""); const [Quote, setText1] = useState(""); const [finalprice,setGCMP1] = useState(''); const [totaltax,setGCMP2] = useState(''); const [ShippingAmount,setGCMP3] = useState(''); const [CostPrice,setGCMP4] = useState(''); const [MarginTotal,setGCMP5] = useState(''); const [ListPrice,setGCMP6] = useState(''); const [SellingPrice,setGCMP7] = useState(''); const [DiscountValue,setGCMP8] = useState(''); const callgcmpapi = () => { const gcmpapi = "https://gcm.dellsvc/GCM.Order.API/api/v1/orders/"+ DPID +"/purchase-summary-with-details?countryCode=US"; Axios.get(gcmpapi).then((response) => { setGCMP1(response.data.Data.PurchaseSummary.PriceSummary.FinalPrice); setGCMP2(response.data.Data.PurchaseSummary.PriceSummary.TaxTotal); setGCMP3(response.data.Data.PurchaseSummary.PriceSummary.ShippingAmount); setGCMP4(response.data.Data.PurchaseSummary.PriceSummary.CostPrice); setGCMP5(response.data.Data.PurchaseSummary.PriceSummary.MarginTotal); setGCMP6(response.data.Data.PurchaseSummary.PriceSummary.ListPrice); setGCMP7(response.data.Data.PurchaseSummary.PriceSummary.SellingPrice); setGCMP8(response.data.Data.PurchaseSummary.PriceSummary.DiscountValue); }) }; // 核心:用useEffect控制API调用时机 useEffect(() => { // 如果DPID为空不需要调用接口可以加判断 if(DPID) { callgcmpapi(); } // 依赖项数组:只有数组内的变量变化时才会重新执行effect逻辑 // 只需要挂载后执行一次就放空数组;要监听props的age变化就把props.age加入依赖数组 }, [DPID]) // 此处补充你需要渲染的组件内容 return ( <div> {/* 你的页面渲染逻辑 */} </div> ) } export default CallAPI;
内容的提问来源于stack exchange,提问作者Raiden Choong
相关产品推荐
相关产品推荐

