React GET API调用中的无限循环以及使用Hooks和useState()的正确方法



我是React的新手,正在为Express.js和MongoDB远程后端开发一个具有标准CRUD操作的应用程序。

在一个页面中,我需要显示使用Axios对远程服务器进行的GET API调用中的值。每个对象都是多个字段,company字段(Exhibitor列中的值,例如类似于5f280eb605c9b25cfeee285c(对应于另一个集合中另一个对象的Mongo对象字段值。

我需要在表中恢复原始值,进行另一个API调用,并从具有该id的对象中获取名称字段(例如公司名称示例字符串(。之后,我需要在表字段中显示它,而不是_id。

例如,为了更清楚地显示item.company字段5f27e8ee4653de50faeb1784将显示为公司名称示例字符串

此外,我还需要对状态列(但没有对远程服务器的GET API调用(执行同样的操作,其中我需要根据项.active值显示图标,该值为布尔值。

这需要在没有任何按钮的情况下完成,但当我自动打开页面时。

我已经制作了一个标准的javascript函数来实现这一点,但我想我得到了一个无限循环,因为React每次渲染时都会调用这个函数。

进行此操作的正确方法是什么?

以下是循环后控制台的错误

xhr.js:178获取http://myserver.com/companies/5f280eb605c9b25cfeee285cnet::ERR_INSUFFERESOURCES

import React, { useState, useEffect, useCallback } from 'react'
import { Tab, Tabs, Col, Form, Button } from 'react-bootstrap'
import { FiTrash, FiCloud, FiPhoneCall, FiUserCheck, FiUserX, FiEye } from 'react-icons/fi'
import axios from 'axios'
const EventProfile = (props) => {
// SOME CODE HERE //
//GET STANDS FROM DB
const [allStands, viewStands] = useState([{}]);
useEffect(() => {
const id = props.match.params.id
const fetchStands = async () => {
const response = await axios.get(`http://myserver.com/stands/${id}`);
viewStands(response.data);
}
fetchStands();
}, [])

// RECOVER NAME USING THE COMPANY ID FROM ANOTHER COLLECTION
const [companyNameGetted, getCompanyName] = useState({})
const getCompanyFromId = useCallback((props) => {
const id = props;
const getCompany = async () => {
const response = await axios.get(`http://myserver.com/companies/${id}`);
getCompanyName(response.data);
}
getCompany([]);
}, [])
// DISPLAY ICON DEPENDING ON OBJECT active FIELD

const handleStandStatus = (status) => {
if(status === true) {
return <FiCloud style={{color: "green"}}/>;
} else {
return <FiCloud style={{color: "grey"}} description="Offline"/>;
}
}

// OTHER CODE HERE //
return (
//SOME CODE HERE//

<Tab eventKey="stands" title="Stands">
<div className="py-12 w-full">
<table className="table table-lg">
<thead>
<tr>
<th>Status</th>
<th>Name</th>
<th>Exhibitor</th>
<th>Size</th>
<th>Color Palette</th>
</tr>
</thead>
<tbody>
{allStands.map((item, index) =>{
return(
<tr key={index}>
<td>{handleStandStatus(item.active)}</td>
<td><Link to={`/standProfile/${item._id}`}>{item.name}</Link></td>
<td>{getCompanyFromId(item.company)}<Link to={`/companyProfile/${item.company}`}><span>{companyNameGetted.name}</span></Link></td>
<td>{item.size}</td>
<td>{item.colorPalette}</td>
</tr>
)
})}
</tbody>
</table>
</div>
</Tab>

// OTHER CODE HERE //
)
}
export default EventProfile

可能这部分负责无限循环:

<td>{getCompanyFromId(item.company)}<Link to={`/companyProfile/${item.company}`}><span>{companyNameGetted.name}</span></Link></td>

因为您在组件的返回中调用了一个函数,然后该函数将调用getCompany函数,该函数将更新您的companyNameGetted状态。

companyNameGetted状态在组件返回中被引用,因此调用getCompanyFromId将导致重新渲染,这将获取公司、更改状态、重新渲染等,从而导致无限循环。

你可以在获得所有展位后,在useEffect中获取公司,也可以设置

useEffect(() => {get all company from allStands}, [allStands]);

因此它将反映CCD_ 5状态的变化。

编辑:这里有一个例子来进一步描述我的意思。

const EventProfile = props => {
// usually you'll want to name the variables as so:
// a noun/object for the first one (stands)
// a setter for the second one, since it is a function to set the `stands`
const [stands, setStands] = useState([]);
const [companies, setCompanies] = useState({});
// usual useEffect that'll be triggered on component load, only one time
useEffect(() => {
const fetchStands = async () => {
const response = await axios.get("stands url here");
setStands(response.data);
};
fetchStands();
}, []);
//another useEffect that'll be triggered when there's a change in the dependency array given, i.e. the `stands` variable. so, it'll fetch company names whenever the `stands` state changes.
useEffect(() => {
const fetchCompanies = async () => {
const newCompanies = {...companies};
// wait for all company names have been retrieved
await Promise.all(stands.forEach(s => {
const id = s.company;
const response = await axios.get("company url here with " + id);
newCompanies[id] = response.data;
}));
setCompanies(newCompanies);
};
fetchCompanies();
}, [stands]);
return (
// ... some components
{stands.map((item, index) => (
<tr key={index}>
<td><Link to={`/some/url/${item.company}`}>{companies[item.company]}</Link></td>
</tr>
)}
);
}

相关内容

最新更新