英文:
Confusion with .then() chaining
问题
我一直在尝试理解 Promises/then-ables 如何工作。
我正在使用 NextJS。
尝试链式操作以执行以下操作:
- 从API获取数据
- 保存数据
- 修改数据以创建组件
(并且不产生无限循环)
我无法获取适当的数据来执行步骤#3。
我尝试了各种方法,但卡在这一步。
我正在使用 useEffect,因为这样做(尽管我确信还有其他方法可以实现):
https://nextjs.org/docs/basic-features/data-fetching/client-side
export default function Survey() {
const [dataDB, setDataDB] = useState('');
let roles = [];
function createCards(rolesArr) {
let role1 = tabs.find(x => x.id == rolesArr[0])
let role2 = tabs.find(x => x.id == rolesArr[1])
let role3 = tabs.find(x => x.id == rolesArr[2])
// 上面的是空的
// 下面的也是空的:
// let role1 = tabs.find(x => x.id == dataDB[0])
roles.push(role1)
roles.push(role2);
roles.push(role3); // 组件将遍历这3个
}
useEffect(() => {
fetch('example.com/api')
.then((response) => response.json()) // 1. 获取像[0, 3, 5]这样的数组
.then((data) => {
setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
}
.then((rolesArr) => createCards(rolesArr)) // 3. 修改数据以供组件使用
})
)
return (
{
roles.map((path) => (
<Card key={path.id}>
<Text>{path.title}</Text>
</Card>
))
}
)
}
英文:
I've been trying to understand how Promises/then-ables work for awhile now.
I'm working with NextJS.
Trying to chain together to do the following:
- Get data from API
- Save the data
- Modify the data to create component
(And not infinite loop)
I can't get the proper data to do step #3.
I've tried various things but am stuck on this step.
I'm using useEffect because of this (though I'm sure there's other ways to do it):
https://nextjs.org/docs/basic-features/data-fetching/client-side
export default function Survey() {
const [dataDB, setDataDB] = useState('');
let roles;
function createCards(rolesArr) {
let role1 = tabs.find(x => x.id == rolesArr[0])
let role2 = tabs.find(x => x.id == rolesArr[1])
let role3 = tabs.find(x => x.id == rolesArr[2])
// the above is null
// the below is also null:
// let role1 = tabs.find(x => x.id == dataDB[0])
roles.push(role1)
roles.push(role2);
roles.push(role3); // component will map over these 3
}
useEffect(() => {
fetch('example.com/api')
.then((response) => response.json()) // 1. Gets an array like [0, 3, 5]
.then((data) => {
setData(dataDB) // 2. Using hook to setData, will store in database later
}
.then((rolesArr) => createCards(rolesArr)) // 3. Modify data for component
})
)
return (
{
roles.map((path) => (
<Card key={path.id}>
<Text>{path.title}</Text>
</Card>
))
}
)
}
答案1
得分: 1
你在这里有很多问题。
roles
未定义
let roles;
创建了一个变量并将其值设置为 undefined
。
下一次你使用它(这里:roles.map((path) => (
),你尝试将其视为数组。
这将导致错误。
你需要在定义时将其设置为一个数组。
拼写错误
> .then((data) => {
> setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
> }
你漏掉了一个 )
。
rolesArr
是 undefined
以下代码块的返回值:
> .then((data) => {
> setData(dataDB) // 2. 使用 hook 设置数据,稍后将存储在数据库中
> }
… 是 undefined
,因为你没有 return
语句,所以链中的下一个 then()
回调将接收到 undefined
。
然而 你没有做任何需要你创建新的 Promise 的事情,所以没有必要使用额外的 then
,只需在你已有的函数中完成所有你想要处理数据的工作。
.then((data) => {
setData(dataDB);
createCards(dataDB);
});
createCards 修改一个不存在且没有被任何地方使用的数组
> roles.push(role1)
> roles.push(role2);
> roles.push(role3); // 组件将遍历这 3 个
你在这里有与之前相同的问题;roles
不是一个数组,它是 undefined
。
而且,由于 createCards
是异步调用的,这段代码将在 roles.map((path) => (
之后运行,所以没有东西会关注这个修改。
不要修改不存在的数组。创建一个新的数组并将其存储在状态中。设置状态将触发重新渲染,所以组件将从状态存储中提取数组并有一些值进行迭代。
通常你会想要做类似于:
const [roles, setRoles] = useState(null);
function createCards(rolesArr) {
// 等等
setRoles([role1, role2, role3]);
}
// 等等
如果 `roles` 为 `null`,则返回 <p>Loading</p>;
return roles.map(等等等等);
英文:
You have a lot of problems here.
roles is undefined
let roles;
creates a variable and sets its value to undefined
.
The next time you touch it (here: roles.map((path) => (
) you are trying to treat it as an array.
This will error.
You need to make it an array when you define it.
a typo
> .then((data) => {
> setData(dataDB) // 2. Using hook to setData, will store in database later
> }
You are missing a )
from the end of there
rolesArr
is undefined
The return value of:
> .then((data) => {
> setData(dataDB) // 2. Using hook to setData, will store in database later
> }
… is undefined
because you have no return
statement, so the next then()
callback in the chain gets passed undefined
.
However you aren't doing anything that requires you to create a new promise there, so there's no point in using an extra then
, just do everything you want to do with the data in the function you already have.
.then((data) => {
setData(dataDB);
createCards(dataDB);
});
createCards modifies an array that doesn't exist and that nothing uses
> roles.push(role1)
> roles.push(role2);
> roles.push(role3); // component will map over these 3
You have the same problem here that you did earlier; roles
isn't an array, it is undefined
.
What's more, because createCards
is called asynchronously, this code will run after roles.map((path) => (
so nothing is going to pay attention to the mutation anyway.
Don't mutate the non-existent array. Create a new one and store it in a state. Setting a state will trigger a re-render so the component will pull the array out of the state storage and have some values to iterate over.
Typically you would want to do something like:
const [roles, setRoles] = useState(null);
function createCards(rolesArr) {
// etc
setRoles([role1, role2, role3]);
}
// etc
if (roles === null) {
return <p>Loading</p>;
}
return roles.map(etc etc);
答案2
得分: 0
使用.then()
时,如果要链式使用一个或多个.then()
,需要从前一个回调函数返回生成的值。例如:
fetchData()
.then((response) => {
console.log(response.json())
return response.json()
}).then((values) => {
console.log(values)
return values.filter((value) => value > 0)
}).then((positiveValues) => {
console.log(positiveValues)
return positiveValues;
})
这个示例将打印response.json()
并将其作为值返回,以便在下一个.then()
回调中使用。
对于您的情况,可以像这样在第二个回调中返回值:
fetch('example.com/api')
.then((response) => response.json()) // 1. 获取一个类似 [0, 3, 5] 的数组
.then((data) => {
setData(dataDB) // 2. 使用 hook 来设置数据,稍后将存储到数据库中
return dataDB;
}).then((rolesArr) => createCards(rolesArr)) // 3. 修改组件的数据
英文:
When using the .then()
, you need to return the resulting value from the previous callback function if you want to chain one or more .then()
. As an example:
fetchData()
.then((response) => {
console.log(response.json())
return response.json()
}).then((values) => {
console.log(values)
return values.filter((value) => value > 0)
}).then((positiveValues) => {
console.log(positiveValues)
return positiveValues;
})
This example will print the response.json()
and return it as a value to be used as an argument on the next .then()
callback.
For your case, return the value inside the second callback like this:
fetch('example.com/api')
.then((response) => response.json()) // 1. Gets an array like [0, 3, 5]
.then((data) => {
setData(dataDB) // 2. Using hook to setData, will store in database later
return dataDB;
}).then((rolesArr) => createCards(rolesArr)) // 3. Modify data for component
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论