我目前正在编码一个函数,用于将blogPost
对象保存到Firestore数据库中的document
中。
预期的例程应为:
savePost()
函数savePost()
函数应调用uploadImagesAndGetURL()
函数,因为在将blogPost
的URL保存到Firestore之前,应将src
的图像上载到Firebase Storage。 (在我的实际情况下,图片上传是async
,我上传的是await
,但我认为这里的示例并不有害)。uploadImagesAndGetURL()
应该上传图像并将返回的urls
存储在src
的{{1}}数组内的各自的elements
属性中。 state
数组上运行forEach()
并调用elements
(setBlogPost)来使用从存储中接收到的新URL更新状态来做到这一点。setState()
函数,该函数应该能够访问最新状态,以便能够将saveToFirestore()
对象以及图像blogPost
保存到数据库中。 / li>
问题
我的问题是,在运行src's
函数时,在这种情况下该组件被重新渲染3次(对于3张图像),因为savePost()
正在调用{{1} } 3次。每个图像一个。当我到达uploadImagesAndGetURL()
功能并登录setBlogPost()
状态时,您可以看到只有第一张图像saveToFirestore()
发生了变化。
我做对了吗?如何改善此例程,以确保在blogPost
之前已更新所有内容?
注意::做到这一点的一种方法是跳过状态更新,并将返回的URL直接传递给src
函数,而无需将其存储在状态中。但是,在这种情况下合适的模式是什么?
通过saveToFirestore()
函数登录:
saveToFirestore()
下面的片段
saveToFirestore()
{
"title": "This is the title",
"body": "Click on the button to upload this post",
"elements": [
{
"type": "image",
"src": "source0"
},
{
"type": "image",
"src": null
},
{
"type": "image",
"src": null
}
]
}
答案 0 :(得分:1)
当您更改博客状态时,可以在useEffect
挂钩中移动保存逻辑,这将触发效果运行。
import React, { useEffect } from "react";
import ReactDOM from "react-dom";
function App() {
console.log("Rendering App...");
const [blogPost, setBlogPost] = React.useState({
title: "This is the title",
body: "Click on the button to upload this post",
elements: [
{ type: "image", src: null },
{ type: "image", src: null },
{ type: "image", src: null }
]
});
function savePost() {
console.log("Inside savePost");
uploadImagesAndGetURL();
// saveToFirestore();
}
function uploadImagesAndGetURL() {
console.log("Inside uploadImages");
const elements = blogPost.elements.map((_, index) => ({
type: "image",
src: `source${index}`
}));
setBlogPost(previousPost => ({ ...previousPost, elements }));
}
// function uploadImagesAndGetURL() {
// console.log("Inside uploadImages");
// blogPost.elements.forEach((item, index) => {
// console.log("Inside uploadImages - forEach");
// setBlogPost(prevState => {
// const aux = Array.from(prevState.elements);
// aux[index].src = "source" + index;
// return {
// ...prevState,
// elements: aux
// };
// });
// });
// }
useEffect(() => {
function saveToFirestore() {
console.log("Inside saveToFirestore");
console.log("Will save the following blogPost to Firestore");
console.log(blogPost);
}
saveToFirestore();
}, [blogPost]);
return (
<React.Fragment>
<div>{blogPost.title}</div>
<div>{blogPost.body}</div>
<div>Image 1 src: {blogPost.elements[0].src}</div>
<div>Image 2 src: {blogPost.elements[1].src}</div>
<div>Image 3 src: {blogPost.elements[2].src}</div>
<button onClick={savePost}>Save Post</button>
</React.Fragment>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
uploadImagesAndGetURL()调用setBlogPost()3次。
而且我实际上还会获得URL列表,并一次性设置elements
属性,以防止3次重新呈现。