如何循环使用 useEffect 和 setState
Posted
技术标签:
【中文标题】如何循环使用 useEffect 和 setState【英文标题】:How to loop in useEffect and setState 【发布时间】:2021-11-04 20:08:06 【问题描述】:我有类别,每个类别都有子类别,我想 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)
,有人知道我想要做什么吗?
【问题讨论】:
这里你需要使用promise,作为你的第二个控制台,即console.log(actual) /* 2 */
在第一个控制台之前执行。所以它打印一个空对象。
【参考方案1】:
您可以使用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 */
)
, [])
【讨论】:
我认为值得一提的是,所有请求都会按顺序进行,加载需要 N×time_to_load_one【参考方案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
那样重复使用相同的变量,这会使代码更难阅读。
【讨论】:
【参考方案3】:在我看来,您需要花时间学习 JS 中的 promise 或 async/await。请原谅我不能花时间写一整篇文章来教所有东西,请谷歌这些关键字。
为了补充使用 async/await 的 @HarshPatel's answer,下面是使用 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)
)
, [])
【讨论】:
以上是关于如何循环使用 useEffect 和 setState的主要内容,如果未能解决你的问题,请参考以下文章