React中Firestore的setDoc/addDoc无法添加文档求助
React项目Firestore setDoc/addDoc无法写入文档排查
问题描述
在React项目中调用Firestore的setDoc或addDoc方法时,无法将文档添加到指定集合,控制台无任何报错输出。已通过登录验证确认Firebase连接正常,传入参数也无问题,求可能原因。
相关代码
FirebaseFile.js
import { initializeApp } from 'firebase/app'; import { getFirestore } from 'firebase/firestore'; var firebaseConfig = { ... }; // Initialize Firebase var app = initializeApp(firebaseConfig); export const db = getFirestore(app);
Another.js
import React, { useRef, useState } from 'react'; import { doc, setDoc,collection } from 'firebase/firestore'; import styled from 'styled-components'; import EmailEditor from '../../../src'; import sample from './sample.json'; import sample2 from './sample2.json'; import sample3 from './sample3.json'; import { db } from '../firebase'; import Checkbox from '@mui/material/Checkbox'; import axios from 'axios'; const label = { inputProps: { 'aria-label': 'Checkbox demo' } }; const Container = styled.div` display: flex; flex-direction: column; position: relative; height: 100%; `; const Bar = styled.div` flex: 1; background-color: #000000; color: #000; padding: 10px; display: flex; max-height: 40px; h1 { flex: 1; font-size: 16px; text-align: left; } button { flex: 1; padding: 10px; margin-left: 10px; font-size: 14px; font-weight: bold; background-color: #000; color: #fff; border: 0px; max-width: 150px; cursor: pointer; } `; const Example = () => { const emailEditorRef = useRef(null); const [titolo, setTitolo] = useState(''); const [newsProfileValue, setNewsProfileSet] = useState(''); const [profileList, setNewsProfileList] = useState([]); const [premiumValue, setPremium] = useState(false); const [publicValue, setPublic] = useState(false); const arr = []; const saveDesign = () => { emailEditorRef.current.editor.saveDesign((design) => { exportData(design); }); }; const getList = async () => { try { //Recupero lo user id var id = await localStorage.getItem('uid'); console.log(id); var data = []; const querySnapshot = await getDocs(collection(db, 'news_profiles')); querySnapshot.forEach((doc) => { if (doc.data().about.uid == id) { data.push({ title: doc.data().about.title, id: doc.id }); arr.push({ doc: doc.data().about.title, id: doc.id }); } }); } catch (error) { console.log('Error: ' + error); } var options = arr.map((e) => { return `<option value="${e.id}">${e.doc}</option>`; }); document.getElementById('selectNumber').innerHTML = options; setNewsProfileList(data); }; const exportData = (design) => { const jsonString = `data:text/json;chatset=utf-8,${encodeURIComponent( JSON.stringify(design) )}`; const link = document.createElement('a'); link.href = jsonString; link.download = 'data.json'; link.click(); }; const exportHtml = () => { console.log('Sono in export html'); addElementToFireStoreNews('prova'); emailEditorRef.current.editor.exportHtml((data) => { const { design, html } = data; console.log('Sono dentor export'); addElementToFireStoreNews(html); console.log("Sono dentor l'export"); }); }; const addElementToFireStoreNewsAWS = async (html) => { var jsonFile; var templateid = await localStorage.getItem('templateid'); if (templateid == 1) { jsonFile = sample; } else if (templateid == 2) { jsonFile = sample3; } else { jsonFile = sample2; } //Salvo la newsletter su aws emailEditorRef.current.editor.exportHtml((data) => { const { design, html } = data; var dataValue = { internal: true, online: publicValue, premium: premiumValue, html: html, template: jsonFile, subject: html, email: uuid, }; axios .post( `https://europe-west3-mindit-newsletter.cloudfunctions.net/newsCreate`, dataValue ) .then((res) => { console.log(res.json()); }); }); }; const addElementToFireStoreNews = async (html) => { console.log("Sono nell'inserimento del html"); try { //addElementToFireStoreNewsAWS(html); var uuid = await localStorage.getItem('uid'); const value = { aboutNews: { email: newsProfileValue, html: html, internal: true, photo: '', title: titolo, }, date: new Date(), id: uuid, measures: { impression: { total: 0, }, views: { moth: 0, total: 0, week: 0, }, }, public: true, searchKey: '', premium: premiumValue, }; const newCityRef = doc(collection(db, 'news')); await setDoc(newCityRef, value); } catch (err) { console.log('Errore inserimnento: ' + err); } }; const onDesignLoad = (data) => { console.log('onDesignLoad', data); }; const onLoad = async () => { getList(); var templateid = await localStorage.getItem('templateid'); if (templateid == 1) { emailEditorRef.current.editor.loadDesign(sample); } else if (templateid == 2) { emailEditorRef.current.editor.loadDesign(sample3); } else { emailEditorRef.current.editor.loadDesign(sample2); } emailEditorRef.current.editor.addEventListener( 'design:loaded', onDesignLoad ); }; const onReady = () => {}; const changeText = (text) => { setTitolo(text); }; const clickValue = (e) => { setNewsProfileSet(e.target.value); }; const changeValue = () => { setPremium(!premium); }; const changeValuePublic = () => { setPublic(!publicValue); }; return ( <Container> <Bar> <img src="firebase.png" width="100" height="50" /> <label style={{ color: 'white' }}> <b>Titolo News: </b> <input type="text" name="name" onChange={(value) => changeText(value.target.value)} style={{ marginRight: 200 }} /> Premium:{' '} <Checkbox {...label} unchecked onClick={() => changeValue()} style={{ color: 'white' }} /> Online:{' '} <Checkbox {...label} unchecked onClick={() => changeValuePublic()} style={{ color: 'white' }} /> </label> <form id="myForm"> <select id="selectNumber" onClick={clickValue}> <option>Scegli il news profile</option> </select> <button onClick={() => saveDesign}> Salva Design </button> <button onClick={() => addElementToFireStoreNews('prova')}> {' '} Salva Articolo{' '} </button>{' '} </form> </Bar> <React.StrictMode> <EmailEditor ref={emailEditorRef} onLoad={onLoad} onReady={onReady} />{' '} </React.StrictMode>{' '} </Container> ); }; export default Example;
可能的原因及排查方案
1. Firestore安全规则限制
这是最常见的原因,默认的Firestore安全规则会拒绝未授权的写入操作。检查Firebase控制台中Firestore的安全规则,确认是否允许当前用户写入news集合。
- 临时测试可将规则设置为开放(仅测试用,上线前务必改回):
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /{document=**} { allow read, write: if true; } } }
- 正式环境应基于用户身份验证设置规则,比如:
allow write: if request.auth != null;
2. 表单提交默认行为未阻止
你在<form>标签内放置了操作按钮,点击时会触发表单默认提交行为,导致页面刷新,异步的setDoc操作可能还未完成就被中断。
- 解决方法:修改按钮点击事件,阻止默认行为:
<button onClick={(e) => { e.preventDefault(); addElementToFireStoreNews('prova'); }}> Salva Articolo </button>
或者将按钮类型设置为button,避免触发表单提交:
<button type="button" onClick={() => addElementToFireStoreNews('prova')}> Salva Articolo </button>
3. 关键变量值异常
检查localStorage.getItem('uid')是否返回预期值,如果uuid为null或undefined,若安全规则依赖id字段匹配用户ID,写入操作会被静默拒绝;另外确认titolo、newsProfileValue等字段是否有符合预期的内容。
4. Date类型序列化问题
Firestore支持JavaScript的Date类型,但某些场景下可能出现序列化异常。可尝试将date字段转换为Firestore时间戳:
import { serverTimestamp } from 'firebase/firestore'; // ... date: serverTimestamp(),
或者转换为ISO字符串:
date: new Date().toISOString(),
5. 依赖版本不兼容
确保firebase和@firebase/firestore依赖版本一致,版本不兼容可能导致静默错误。可尝试更新到最新稳定版本:
npm install firebase@latest
内容的提问来源于stack exchange,提问作者riki
相关产品推荐
相关产品推荐

