如何在 useEffect 和 setState 中循环
How to loop in useEffect and setState
我有类别,每个类别都有子类别,我想设置一个像
这样的字典
{category1.name: [/*list of all subcategories*/], category2.name: [...]}
我有
useEffect(()=>{
Axios.get("http://localhost:3001/categories/get").then((p) => { /* return a list of categories */
setCategories(p.data)
let actual = {}
for (let i = 0; i < p.data.length; i++) {
Axios.get("http://localhost:3001/category/subcategories", { /* return all the subcategories of p.data[i], this is working! */
params : {category : p.data[i].category}}).then((p) => {
actual = {...actual, [p.data[i].category]: p.data}
console.log(actual) /* 1 */
})
}
console.log(actual) /* 2 */
})
}, [])
我已经让后端工作了,但是当我 console.log(actual) /* 2 */
它只是一个空字典 {}
;当我 console.log(actual) /* 1 */
它不为空(只有 1 个元素)时,我不知道我什么时候可以 setState(actual)
,有人知道如何做我想做的事吗?
您只需使用 async/await
即可满足您的需求。
编辑(@skyboyer 提到):
当您进行网络调用时,所有请求将按顺序进行,加载需要 N×time_to_load_one
试试这个。
useEffect(()=>{
Axios.get("http://localhost:3001/categories/get").then(async (p) => { /* return a list of categories */
setCategories(p.data)
let actual = {}
for (let i = 0; i < p.data.length; i++) {
await Axios.get("http://localhost:3001/category/subcategories", { /* return all the subcategories of p.data[i], this is working! */
params : {category : p.data[i].category}}).then((p) => {
actual = {...actual, [p.data[i].category]: p.data}
console.log(actual) /* 1 */
})
}
console.log(actual) /* 2 */
})
}, [])
这应该能让您走上正轨
useEffect(() => {
(async() => {
const p = await Axios.get("http://localhost:3001/categories/get")
setCategories(p.data)
let actual = {}
for (let i = 0; i < p.data.length; i++) {
const x = await Axios.get("http://localhost:3001/category/subcategories", { /* return all the subcategories of p.data[i], this is working! */
params: {
category: p.data[i].category
}
})
actual = {...actual, [x.data[i].category]: x.data
}
console.log(actual) /* 1 */
}
console.log(actual) /* 2 */
})();
}, [])
同时避免重复使用与 p
相同的变量,这会使阅读代码变得更加困难。
在我看来,你需要花时间学习JS中的promise或async/await。原谅我不能花时间写一整篇文章来教大家,请google这些关键词。
为了补充使用 async/await 的 ,下面是一个使用 promise 的解决方案。他的解决方案是按顺序发出请求,而我的是同时发出请求。
useEffect(() => {
Axios.get("http://localhost:3001/categories/get").then((p) => {
/* return a list of categories */
setCategories(p.data)
const tasks = p.data.map((category) => {
return Axios.get(
"http://localhost:3001/category/subcategories",
{ params: { category } }
).then((p) => {
return { [category]: p.data }
})
})
Promise.all(tasks).then(results => {
const actual = results.reduce((acc, item) => {
return { ...acc, ...item }
}, {})
})
setState(actual)
})
}, [])
我有类别,每个类别都有子类别,我想设置一个像
这样的字典{category1.name: [/*list of all subcategories*/], category2.name: [...]}
我有
useEffect(()=>{
Axios.get("http://localhost:3001/categories/get").then((p) => { /* return a list of categories */
setCategories(p.data)
let actual = {}
for (let i = 0; i < p.data.length; i++) {
Axios.get("http://localhost:3001/category/subcategories", { /* return all the subcategories of p.data[i], this is working! */
params : {category : p.data[i].category}}).then((p) => {
actual = {...actual, [p.data[i].category]: p.data}
console.log(actual) /* 1 */
})
}
console.log(actual) /* 2 */
})
}, [])
我已经让后端工作了,但是当我 console.log(actual) /* 2 */
它只是一个空字典 {}
;当我 console.log(actual) /* 1 */
它不为空(只有 1 个元素)时,我不知道我什么时候可以 setState(actual)
,有人知道如何做我想做的事吗?
您只需使用 async/await
即可满足您的需求。
编辑(@skyboyer 提到):
当您进行网络调用时,所有请求将按顺序进行,加载需要 N×time_to_load_one
试试这个。
useEffect(()=>{
Axios.get("http://localhost:3001/categories/get").then(async (p) => { /* return a list of categories */
setCategories(p.data)
let actual = {}
for (let i = 0; i < p.data.length; i++) {
await Axios.get("http://localhost:3001/category/subcategories", { /* return all the subcategories of p.data[i], this is working! */
params : {category : p.data[i].category}}).then((p) => {
actual = {...actual, [p.data[i].category]: p.data}
console.log(actual) /* 1 */
})
}
console.log(actual) /* 2 */
})
}, [])
这应该能让您走上正轨
useEffect(() => {
(async() => {
const p = await Axios.get("http://localhost:3001/categories/get")
setCategories(p.data)
let actual = {}
for (let i = 0; i < p.data.length; i++) {
const x = await Axios.get("http://localhost:3001/category/subcategories", { /* return all the subcategories of p.data[i], this is working! */
params: {
category: p.data[i].category
}
})
actual = {...actual, [x.data[i].category]: x.data
}
console.log(actual) /* 1 */
}
console.log(actual) /* 2 */
})();
}, [])
同时避免重复使用与 p
相同的变量,这会使阅读代码变得更加困难。
在我看来,你需要花时间学习JS中的promise或async/await。原谅我不能花时间写一整篇文章来教大家,请google这些关键词。
为了补充使用 async/await 的
useEffect(() => {
Axios.get("http://localhost:3001/categories/get").then((p) => {
/* return a list of categories */
setCategories(p.data)
const tasks = p.data.map((category) => {
return Axios.get(
"http://localhost:3001/category/subcategories",
{ params: { category } }
).then((p) => {
return { [category]: p.data }
})
})
Promise.all(tasks).then(results => {
const actual = results.reduce((acc, item) => {
return { ...acc, ...item }
}, {})
})
setState(actual)
})
}, [])