В настоящее время я кодирую функцию для сохранения объекта blogPost
в document
в моей базе данных Firestore.
Предполагаемая процедура должна быть:
- Нажмите наКнопка SAVE и вызов функции
savePost()
- Функция
savePost()
должна вызывать функцию uploadImagesAndGetURL()
, потому что изображения blogPost
должны быть загружены в Firebase Storage до того, как я сохраню их src
URL-адрес вПожарный магазин.(в моем реальном случае загрузка изображения async
, и я await
для его завершения, но я не думаю, что это повредит приведенному здесь примеру). uploadImagesAndGetURL()
должен загрузить изображения исохранить возвращенные значения urls
для каждого из них в соответствующем свойстве src
внутри массива elements
state
. - Это выполняется путем запуска
forEach()
в массиве elements
и вызова setState()
(setBlogPost) для обновления состояния новыми URL-адресами, полученными из хранилища. - * 1031Затем будет вызвана функция *, и она сможет получить доступ к самому последнему состоянию, чтобы иметь возможность сохранить объект
blogPost
вместе с изображением src's
в базе данных.
ВОПРОС
Моя проблема в том, что во время выполнения функции savePost()
компонент в этом случае перерисовывается 3 раза (для 3 изображений), поскольку uploadImagesAndGetURL()
вызывает setBlogPost()
три раза.Один для каждого изображения.И когда я достигаю функции saveToFirestore()
и регистрирую состояние blogPost
, вы видите, что изменилось только первое изображение src
.
Я правильно делаю?Как я могу улучшить эту процедуру, чтобы убедиться, что все было обновлено до I saveToFirestore()
?
ПРИМЕЧАНИЕ: Один из способов сделать это - пропустить обновление состояния и передать возвращенные URL-адреса прямо в функцию 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
}
]
}
SNIPPET НИЖЕ
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');
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
});
});
});
}
function saveToFirestore() {
console.log('Inside saveToFirestore');
console.log('Will save the following blogPost to Firestore');
console.log(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'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>