只有 运行 次 useEffect 提取在第一次 useEffect 提取被触发并在上下文中设置用户之后
Only run a useEffect fetch after first useEffect fetch has fired and setUser in context
我需要调用保管箱 api 两次。第一个 useEffect 获取名称和路径,然后将它们推送到上下文中的空白数组中。然后我需要触发第二个 useEffect,它依赖于从第一个 useEffect 填充的数组。我尝试使用 useState 并创建 loading 和 setLoading,然后将 useEffect 的内部包装在 if(loading) 中,但这没有用,因为我猜它只会在安装组件时尝试触发。如何在第一个 useEffect 完成后制作第二个 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,
});
}, []);
我认为它与依赖项数组有关,但我放入其中的所有内容(如用户、setUser)都给了我一个无限循环,console.log 用于 user.imagePaths记录为 []。我知道 user.imagePaths 是在第一个 useEffect 之后填充的,但是第二个 useEffect 对于循环的 user.imagePaths.length 一直未定义。
您应该将user.imagePaths添加到第二个useEffect的依赖列表中。
我建议使用 async/await 并在单个 useEffect 中进行调用。
如果默认情况下未定义 user,那么您可能需要添加可选链接。
[更新]
尝试将第二个 useEffect 更改为:
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(() => {
...
}, [])
您的第二个 useEffect 将仅在数组 listFolders 更改时加载。
除此之外,这里的目标是连接您所有的承诺,以便它只更新一次用户。否则我们会遇到异步的麻烦。
useEffect(() => {
if(listFolders.length){
Promise.all([*put all your promise here*]).then((data) => {
* concatenate your array of link
setUser({
...user,
imageLinks: arrayOfLinks,
})
})
}
}, [listFolders])
我需要调用保管箱 api 两次。第一个 useEffect 获取名称和路径,然后将它们推送到上下文中的空白数组中。然后我需要触发第二个 useEffect,它依赖于从第一个 useEffect 填充的数组。我尝试使用 useState 并创建 loading 和 setLoading,然后将 useEffect 的内部包装在 if(loading) 中,但这没有用,因为我猜它只会在安装组件时尝试触发。如何在第一个 useEffect 完成后制作第二个 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,
});
}, []);
我认为它与依赖项数组有关,但我放入其中的所有内容(如用户、setUser)都给了我一个无限循环,console.log 用于 user.imagePaths记录为 []。我知道 user.imagePaths 是在第一个 useEffect 之后填充的,但是第二个 useEffect 对于循环的 user.imagePaths.length 一直未定义。
您应该将user.imagePaths添加到第二个useEffect的依赖列表中。
我建议使用 async/await 并在单个 useEffect 中进行调用。
如果默认情况下未定义 user,那么您可能需要添加可选链接。
[更新]
尝试将第二个 useEffect 更改为:
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(() => {
...
}, [])
您的第二个 useEffect 将仅在数组 listFolders 更改时加载。 除此之外,这里的目标是连接您所有的承诺,以便它只更新一次用户。否则我们会遇到异步的麻烦。
useEffect(() => {
if(listFolders.length){
Promise.all([*put all your promise here*]).then((data) => {
* concatenate your array of link
setUser({
...user,
imageLinks: arrayOfLinks,
})
})
}
}, [listFolders])