reactjs - 在 React 中执行 API 调用之前检查 setState 是否已运行
问题描述
我有一个带有文本字段的表单和一个接受多个文件的表单输入。OnSubmit 将文件发送到 Firebase 存储,后者会发回每个文件的 URL。然后将这些 URL 存储在表单对象的“photosURL”数组中,然后将其发布到 MongoDB。
问题是,每次我将表单对象数据发布到 Mongo 时,照片数组都是空的,尽管控制台日志显示它在我调用 post-to-Mongo 代码之前已被填充。这使我认为 post-to-Mongo 代码在使用照片 URL 填充之前使用表单对象值。
问题是,在运行代码将数据推送到 MongoDB 之前,如何检查照片数组是否已填充?我已经在使用 Promise.all 理论上等待发送所有文件并返回 URL,但我无法弄清楚为什么每次将数据发送到 Mongo 时 photoURLs 数组都是空的。
这是代码:
const [form, setForm] = useState({
userId: '',
post: '',
createdAt: createdAt,
photoURLs: [],
})
const handleSubmit = (e) => {
e.preventDefault()
newPost ? postData(form) : ...
}
// SEND FILE TO FIREBASE AND GET BACK THE URL
async function handleUpload(file) {
const storageRef = useStorage.ref("PostImages");
const fileRef = storageRef.child(`${nanoid()}`);
return fileRef.put(file).then(() => {
return fileRef.getDownloadURL().then(function (url) {
photoArray.push(url);
setForm(prevState => ({ ...prevState, photos: photoArray }))
});
});
}
// POST FUNCTION
const postData = async (form) => {
setLoading(true)
let thisFileArray = fileInput.current.files;
const uploadTasks = [];
for (let i = 0; i < thisFileArray.length; i++) {
uploadTasks.push(handleUpload(thisFileArray[i]));
}
Promise.all(uploadTasks).then(() => {
axios.post('/api/posts', form)
.then(response => {
...
})
.catch(error => {
...
})
})
}
谁能看看出了什么问题?
编辑:这是表单对象的控制台日志,在 axios.post 代码之前调用(它显示填充的 photosURL):
createdAt: 1630072305502
photos:
0: "https://firebasestorage.googleapis.com/..."
1: "https://firebasestorage.googleapis.com/..."
post: "sample text"
userId: "1iNGV..."
解决方案
我认为您遇到了时间问题。
不要忘记 React 状态更新是异步的,如此处所述。
我建议直接传递您的 URL,而不是通过组件的状态:
async function handleUpload(file) {
const storageRef = useStorage.ref("PostImages");
const fileRef = storageRef.child(`${nanoid()}`);
await fileRef.put(file);
const url = await fileRef.getDownloadURL();
return url; // Send back the download URL
}
const postData = async (form) => {
setLoading(true);
let thisFileArray = fileInput.current.files;
const uploadTasks = [];
for (let i = 0; i < thisFileArray.length; i++) {
uploadTasks.push(handleUpload(thisFileArray[i]));
}
const photos = await Promise.all(uploadTasks); // Get all URLs here
await axios.post('/api/posts', {...form, photos}); // Send URLs to your server
setLoading(false);
}
推荐阅读
- c - 警报响起时正在生成核心
- c++ - 哪种 c++ stl 数据结构对于存储唯一值及其计数最有效?
- api - 使用Jenkins rest api创建作业时如何获取JSON格式的响应体?
- python - 在没有浏览器活动的情况下使用 Python API 在 Google 驱动器上上传文件
- microsoft-graph-api - 我在哪里可以获得 groupId?
- javascript - SyntaxError:不能在没有模块的情况下使用导入语句,TypeError [ERR_UNKNOWN_FILE_EXTENSION]:Catch 22
- ios - IOS 限制对某些国家或 WLAN 的应用程序的访问
- php - 如果未启用“管理库存”并排除 WooCommerce 中的某些产品类别,则显示自定义库存消息
- php - 注册后隐藏输入的未定义变量 - Laravel
- javascript - 事件中没有功能的欧拉图