簡體   English   中英

useEffect 覆蓋 state 而不是在進行 firestore 調用時附加值

[英]useEffect overriding the state instead of appending the values while making firestore calls

const [data, setData] = useState([])
    
     const getDataFromFirebase = async () => {
         let response = await firestore.collection('someDatabase').get()
         response.forEach(item => setData([...data, item.data().name]))
         
     }
    
    useEffect(() => {
       getDataFromFirebase()
    },[])

data 被最新值覆蓋,而不是將所有值添加到數組中。

setData中使用回調

setData(prevState => ([
    ...prevState, item.data().name
]));

原因是添加項目所花費的時間非常少,這就是為什么在反映之前,它被覆蓋了。 您必須在 setData 中使用 prevState。 嘗試這個:

 const [data, setData] = useState([]) const getDataFromFirebase = async () => { let response = await firestore.collection('someDatabase').get() response.forEach(item => setData(prevState => ([...prevState, item.data().name]) ); } useEffect(() => { getDataFromFirebase() },[])

let response = await firestore.collection('someDatabase').get()
response.forEach(item => setData([...data, item.data().name]))

我不熟悉firestore ,但 promise 將被解決一次,你應該這樣做:

const dataToAdd = response.map(item => item.data().name)
setData(prevState => ([...prevState, ...dataToAdd])

每次調用setData時,您都會重新渲染組件,並且您不應該在同步循環中執行此操作。

prevState在這里是必要的,因為您正在異步 function 中工作。 從理論上講,如果您不在其他任何地方更改 state,則在使用帶有dataToAdd的解決方案后,它應該可以在沒有它的情況下工作。

嘗試此觸發 setState 一次,但在此之前構建數組:

const [data, setData] = useState([])
    
 const getDataFromFirebase = async () => {
    let response = await firestore.collection('someDatabase').get()
    const d = response.map(item=> item.data().name)
    setData(d)  
  }
    
 useEffect(() => {
       getDataFromFirebase()
 },[])

多次觸發setData會導致多次重新渲染,所以這里只觸發一次。

在您下面的代碼中,即使您稍后更改數據,數據的值也將始終為[]

const getDataFromFirebase = async () => {
         let response = await firestore.collection('someDatabase').get()
         response.forEach(item => setData([...data, item.data().name]))
         
     }

這就是文檔所說的

function 組件(稱為 React 的渲染階段)的主體中不允許發生突變、訂閱、計時器、日志記錄和其他副作用。 這樣做會導致 UI 中出現令人困惑的錯誤和不一致。

在每個循環中調用 setData 並不是一個好主意。 一旦循環完成,填充一個數組並將其傳遞給setData

     const getDataFromFirebase = async () => {
         let response = await firestore.collection('someDatabase').get();
         let newData = [];
         response.forEach(item => newData.push(item.data().name));

         // now set the new data
         setData(prevData=> ([...prevData, ...newData]));
         
         // or you can use Array.concat
         // setData(prevData=> (prevData.concat(newData)));
     }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM