如何在不使用 useEffect 的情况下等待 useState 钩子值更新?
我有一个包含帖子的社交媒体 Web 应用程序。我试图让用户从 React 前端将图片上传到 Cloudinary。有时帖子会附加图片,有时则不附加。
如果有图片,我想等待图片上传到 Cloudinary,然后,一旦 API 返回了图片 URL,就继续将该
imageURL
连同其他帖子数据一起上传到我的 Mongo db 进行永久存储。
我遇到的问题是,我需要等待 API 返回
imageURL
,然后才能将数据发布到我的数据库。目前我有一个函数
uploadImage()
,它附加到一个
handlesubmit()
函数,该函数附加到一个用户填写的表单,以设置图像和发布内容。
我的尝试是有一个
useState
钩子
setImgURL
,当 API 返回图像 URL 时更新,然后在另一个
fetch()
发布请求中使用此变量到我的 mongodb 数据库进行存储。
但是我后来了解到
useState
钩子是异步的。这会导致我的帖子图片 URL 在 API 实际返回实际图片 URL 之前以空白值添加到 mongodb,因此丢失(如果用户在 Cloudinary 给我图片 URL 之前快速提交表单,则尤其如此)。
我怎样才能等待图片上传到 Cloudinary,获取 URL,然后再将其最终位置发布到我的数据库?
我认为我不能使用
useEffect()
钩子,这是解决这个问题的标准建议,因为我只有一次机会将
imageURL
上传到后端数据库。我需要等到我有该值后才能将帖子详细信息上传到 mongo。我想我可以获取新的帖子 ID,然后执行
useEffect
,在后端通过 Cloudinary 图像 URL 发出更新请求,但这似乎是错误的方法。
代码:
const [imgURL, setImgURL] = useState(null);
const uploadImage = async (image) => {
console.log('uploading image');
const formData = new FormData();
formData.append('file', image);
formData.append("upload_preset", presetValue);
try{
const response = await fetch(APIendPointURL,
{
method: 'POST',
body: formData
});
const data = await response.json();
console.log(data);
setImgURL(data.secure_url);
console.log(imgURL)
} catch(err){
console.log(err);
setErrors(err);
}
}
我在表单
handleSubmit()
函数中调用
uploadImage()
:
const handleSubmit = async (e) => {
if (image){
await UploadImage(image);
}
//send post data to mongodb
try{
const response = await fetch('http://localhost:3000/api/v1/post/create',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
},
body: JSON.stringify({
content: e.target.content.value,
imgURL: imgURL
})
});
const data = await response.json();
console.log(data);
} catch(err){
console.log(err);
setErrors(err);
}
}
我认为您不需要将
imgURL
设置为状态。
const uploadImage = async (image) => {
console.log('uploading image');
const formData = new FormData();
formData.append('file', image);
formData.append("upload_preset", presetValue);
try{
const response = await fetch(APIendPointURL,
{
method: 'POST',
body: formData
});
const data = await response.json();
console.log(data);
return data.secure_url; // NOT setImgURL(data.secure_url);
} catch(err){
console.log(err);
setErrors(err);
}
}
const handleSubmit = async (e) => {
let imgURL = "";
if (image){
imgURL = await uploadImage(image);
}
//send post data to mongodb
try{
const response = await fetch('http://localhost:3000/api/v1/post/create',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': localStorage.getItem('token')
},
body: JSON.stringify({
content: e.target.content.value,
imgURL: imgURL
})
});
const data = await response.json();
console.log(data);
} catch(err){
console.log(err);
setErrors(err);
}
}
希望这对您有所帮助。
为了等到状态更新其值,有一个称为
flushSync
的东西可以从
react-dom
导入。
它的作用是
flushSync lets you force React to flush any updates inside the provided callback synchronously. This ensures that the DOM is updated immediately.
import {flushSync} from 'react-dom'
// in a component
flushSync(()=>{
setState(value)
})
// The below code will only run the state in `flushSync` has updated.