仅在第一次useEffect获取已激发并在上下文中设置User之后运行useEffect提取



我需要调用dropbox api两次。第一个useEffect获取名称和路径,然后将它们推入上下文中的空白数组中。然后我需要第二个useEffect来激发它,它依赖于从第一个useEffect填充的数组。我曾尝试使用State并创建loading和setLoading,然后将useEffect的内部封装在and if(loading(中,但这没有奏效,因为我猜它只会在安装组件时尝试激发。在第一个useEffect完成后,我如何运行第二个?

const [user, setUser] = useContext(UserContext);

首次使用效果:

useEffect(() => {
var myHeaders = new Headers();
myHeaders.append(
'Authorization',
'Bearer XXXXXXXXXXXXXXX',
);
myHeaders.append('Content-Type', 'application/json');
var raw = JSON.stringify({path: `/${user.username}`});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
};
fetch('https://api.dropboxapi.com/2/files/list_folder', requestOptions)
.then(response => response.json())
.then(data => {
let tmpArray = [];
let tmpArrayTwo = [];
for (var i = 0; i < data.entries.length; i++) {
tmpArray.push(data.entries[i].name);
tmpArrayTwo.push(data.entries[i].path_lower);
}
setUser({
...user,
imageNames: tmpArray,
imagePaths: tmpArrayTwo,
});
})
.catch(error => console.log('error', error));
}, []);

第二次使用效果:

useEffect(() => {
let tmpArray = [];
var myHeaders = new Headers();
myHeaders.append(
'Authorization',
'Bearer XXXXXXXXXXXXXX',
);
myHeaders.append('Content-Type', 'application/json');
for (var i = 0; i < user.imagePaths.length; i++) {
var raw = JSON.stringify({path: `/${user.imagePaths[i]}`});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
};
fetch(
'https://api.dropboxapi.com/2/files/get_temporary_link',
requestOptions,
)
.then(response => response.json())
.then(data => {
tmpArray.push(data.link);
})
.catch(error => console.log('error', error));
}
console.log(tmpArray);
setUser({
...user,
imageLinks: tmpArray,
});
}, []);

我认为这与依赖数组有关,但我在其中放入的所有内容(如user、setUser(都给了我一个无限循环,user.imagePaths的console.log一直记录为[]。我知道user.imagePaths是在第一个useEffect之后填充的,但循环的user.imagePaths.length一直没有定义第二个useEffect。

您应该将user.imagePaths添加到第二个useEffect的依赖项列表中。

不过,我建议使用async/await并在singleuseEffect中进行调用。

如果用户在默认情况下未定义,那么您可能需要添加可选的链接。

[更新]

尝试将第二个用途更改为:

useEffect(() => {
var myHeaders = new Headers();
myHeaders.append(
'Authorization',
'Bearer XXXXXXXXXXXXXX',
);
myHeaders.append('Content-Type', 'application/json');
if (!user?.imagePaths) {
return;
}
Promise.all(user.imagePaths.map(path => {
var raw = JSON.stringify({path: `${path}`});
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow',
};
return fetch(
'https://api.dropboxapi.com/2/files/get_temporary_link',
requestOptions,
)
.then(response => response.json())
.then(data => data.link)
.catch(error => console.log('error', error));
}),
).then(imageLinks => {
setUser({
...user,
imageLinks,
});
});
}, [user?.imagePaths]);

根据我的理解。我建议您首先使用一个状态,以便在React的生命周期中拥有您的数据。

const [listFolders, setListFolders] = React.useState([])
const [user, setUser] = React.useState({})

您的第一个useEffect将加载在组件的第一个挂载上,并且由于函数末尾的[]位置,因此在之后不会得到回调。这允许告诉React只在没有依赖关系的情况下触发效果。

useEffect(() => {
...
}, [])

只有当数组listFolders发生更改时,才会加载第二个useEffect。除此之外,这里的目标是连接所有的承诺,这样它只更新一次用户。否则我们会遇到异步问题。

useEffect(() => {
if(listFolders.length){
Promise.all([*put all your promise here*]).then((data) => {
* concatenate your array of link
setUser({
...user,
imageLinks: arrayOfLinks,
})
})
}
}, [listFolders])