reactjs - 根据下拉列表从 2 个 API 和 setState 获取详细信息 - React 功能组件
问题描述
我有一个名为 Calendar 的功能组件,其中每个月都是一个按钮。我设计了两个 API:
第一个在第一次加载时从 API 中获取数据,并且没有从下拉列表中选择任何内容。以下是 Postman 上的输出:
[ { "month": 1, "count": 5 }, { "month": 3, "count": 2 }, { "month": 10, "count": 4 }, { "month": 11, "count": 3 }
]`
现在我有以下状态,
const [jan, setJan] = useState(0);
const [feb, setFeb] = useState(0);
const [mar, setMar] = useState(0);
const [apr, setApr] = useState(0);
const [may, setMay] = useState(0);
const [june, setJune] = useState(0);
const [july, setJuly] = useState(0);
const [aug, setAug] = useState(0);
const [sept, setSept] = useState(0);
const [oct, setOct] = useState(0);
const [nov, setNov] = useState(0);
const [dec, setDec] = useState(0);
const [month, setMonth] = useState([]);
const cleanup = () =>{
setJan(0);
setFeb(0);
setMar(0);
setApr(0);
setMay(0);
setJune(0);
setJuly(0);
setAug(0);
setSept(0);
setOct(0);
setNov(0);
setDec(0);
}
const [month, setMonth] = useState([]);
const [name, setName] = useState("");
每个月的状态应该根据下拉列表改变,如果我选择一个学生说Rani,应该显示她每个月的总分,如果我选择Ramu,他的分数应该显示在按钮上。现在,我有 2 个不同的 API,如果没有选择名称,则默认 api 获取信息,如果没有,另一个具有 studentname 的 api 根据选择的学生获取信息。
假设,我从下拉列表中选择 Rani,并根据下面给出的 API 输出:
[
{
"month": 11,
"count": 1
}
]
只有 11 月按钮应显示计数为 1,其余为 0。如果我未在下拉列表中选择任何内容,则默认 API 应该可以工作。我设计了下面的代码,它在正确加载时显示通知的数量,但是一旦我更改名称并且再次不选择任何内容,所有月份它都显示为 0。下面是相同的 useEffect 代码。
useEffect(() => {
if(name!=""){
cleanup();
axios.get("http://localhost:8081/api/teacherportal/1234/${name}")
.then(res => {
setMonth(res.data)
month.forEach(mon => {
{
(month.map(mon => {
if (mon["month"] === 1)
setJan(mon["count"]);
else if (mon["month"] === 2)
setFeb(mon["count"]);
else if (mon["month"] === 3)
setMar(mon["count"]);
else if (mon["month"] === 4)
setApr(mon["count"]);
else if (mon["month"] === 5)
setMay(mon["count"]);
else if (mon["month"] === 6)
setJune(mon["count"]);
else if (mon["month"] === 7)
setJuly(mon["count"]);
else if (mon["month"] === 8)
setAug(mon["count"]);
else if (mon["month"] === 9)
setSept(mon["count"]);
else if (mon["month"] == 10)
setOct(mon["count"]);
else if (mon["month"] === 11)
setNov(mon["count"]);
else if (mon["month"] === 12)
setDec(mon["count"]);
}
))
}
})
})
.catch(err => { console.log(err) })
}
else{
axios.get("http://localhost:8081/api/teacherportal/1234")
.then(res => {
setMonth(res.data)
month.forEach(mon => {
{
(month.map(mon => {
if (mon["month"] === 1)
setJan(mon["count"]);
else if (mon["month"] === 2)
setFeb(mon["count"]);
else if (mon["month"] === 3)
setMar(mon["count"]);
else if (mon["month"] === 4)
setApr(mon["count"]);
else if (mon["month"] === 5)
setMay(mon["count"]);
else if (mon["month"] === 6)
setJune(mon["count"]);
else if (mon["month"] === 7)
setJuly(mon["count"]);
else if (mon["month"] === 8)
setAug(mon["count"]);
else if (mon["month"] === 9)
setSept(mon["count"]);
else if (mon["month"] == 10)
setOct(mon["count"]);
else if (mon["month"] === 11)
setNov(mon["count"]);
else if (mon["month"] === 12)
setDec(mon["count"]);
}
))
}
})
})
.catch(err => { console.log(err) })
}
}, [month,name]);
下面是下拉 onChange 处理程序:
const handleChange = (event) => {
setCustomer(event.target.value);
if (event.target.value === "Rani") {
setName("Rani");
}
else if (event.target.value === "Ramu") {
setName("Ramu");
}
else if (event.target.value === "Lalu") {
setName("Lalu");
}
}
如果我从下拉列表中选择学生,并且该学生的某个月份没有数据,则从默认 api 获取的数据将被覆盖而不是显示 0,因此会显示清理功能。有人可以帮忙吗,提前谢谢你:)
解决方案
我认为问题在于你是同一个函数中的setMonth
和month
变量。setMonth
不会month
直接更新变量,而是在下一次渲染调用中执行此操作。
setMonth
要解决您的问题,请在两次调用中收到数据后绕过:
axios.get("http://localhost:8081/api/teacherportal/1234/${name}")
.then(res => {
res.data.forEach(mon => {
尽管此代码可能有效,但可以简化很多。
将您的月份数据存储在一个单独useState
的文件中可以更容易阅读,并且意味着不再需要从月份(数字)到 setState 函数的映射。
// array with 12 entries
const [months, setMonths] = useState(Array(12).fill(0));
// jan = months[0];
// feb = months[1];
// ...
在您的useEffect
钩子中,处理 API 响应的代码是相同的。您可以删除很多代码(并使用上面的单个 useState)使其看起来像这样:
useEffect(() => {
const getData = async () => {
if (name !== '') {
return axios.get('http://localhost:8081/api/teacherportal/1234/${name}');
}
return axios.get('http://localhost:8081/api/teacherportal/1234');
};
getData()
.then(({ data }) => {
// start with empty months data (same as `cleanup()`)
const monthsData = Array(12).fill(0);
// populate the new array with your API data
data.forEach(entry => {
// the API returns the month starting from 1, while the array index starts from 0.
monthsData[entry.month - 1] = entry.count;
});
setMonths(monthsData);
})
.catch(error => {
console.log('Failed to get data', error)
});
}, [name]);
最后,handleChange 函数可以简化为:
const handleChange = (event) => {
setCustomer(event.target.value);
setName(event.target.value);
}
推荐阅读
- linux - 用于链路层协议的数据包嗅探器
- python - 如果您的数据具有单个特征,则使用 array.reshape(-1, 1) 重塑您的数据,如果它包含单个样本错误,则使用 array.reshape(1, -1)
- java - @JsonIgnoreProperties JPA - 不忽略属性
- flutter - 通过 Flutter 中的按钮输入更改主题
- azure - 使用应用注册的 Azure AD 自动用户预配
- android - Firebase实时数据库未在android studio中写入任何值
- java - 使用 JOptionPane 将字符串数组转换为 int
- css - flex-wrap 不起作用的原因是什么?
- typescript - 如何将 svelte-preprocess 的结果发送到文件中
- pagination - Material Paginator:转到特定页码