我下面有这个JavaScript代码:
const getProducts = () => {
votationRef
.child(moment().format('yyyy-MM-DD'))
.once('value').then((snapshot) => {
try {
var productsId = snapshot.val();
productsId.map((item) => {
productsRef
.child(item)
.once('value')
.then((snapshot) => {
setProducts([...products, snapshot.val()]);
})
})
} catch (e) {
console.log('ERROR', e.message)
}
})
}
简而言之,在DOM完成加载之前,使用getProducts
钩子调用了函数useEffect
。
此功能的任务是(按每个productsId
检索存储在我的Firebase RT DB中的每个产品的详细信息,并将它们放入状态数组(setProducts
)。
最终的products
数组结果在我的JSX中只是显示为“段落列表”。这是代码:
products.map((item) => {
return <p>{item.name}</p>
})
有人可以向我解释为什么在以上过程结束时我的React状态products
仅包含Firebase“产品”文档节点中最后一个产品的详细信息吗?
当前,我的firebase“产品”文档节点包含以下数据:
"products" : {
"-MK-CnXnTYbyYm5eyYBK" : {
"coverImg" : "https://firebasestorage.googleapis.com/v0/b/onebidup.appspot.com/o/images%2FcoverImages%2F32a01e12-e7a2-44df-ac62-5d5eac00d031.jpg?alt=media&token=7b9b8304-c0b1-4123-85fd-b0fe4096d3d0",
"description" : "Audio che riempie la stanza - I cinque altoparlanti offrono bassi potenti, medi dinamici e alti nitidi",
"maxVote" : 5,
"name" : "Echo Studio - Altoparlante intelligente",
"price" : "189.99"
},
"-MKFOYfuAdK8Fo4l-aiV" : {
"coverImg" : "https://firebasestorage.googleapis.com/v0/b/onebidup.appspot.com/o/images%2FcoverImages%2F8e1edf42-562b-4a05-8180-b320968b1024.jpg?alt=media&token=ffad077c-014c-4a60-aab0-edb2cbe526f5",
"description" : "La serie Q64 è una variante di colore silver della serie Q60 a cui aggiunge il telecomando Premium Metal One Remote e la tecnologia di controllo dell’immagine Ultimate UHD Dimming",
"name" : "Samsung QE55Q64RATXZT Serie Q64R QLED Smart TV 55\", Ultra HD 4K, Wi-Fi, Silver, 2019",
"price" : "669"
},
"-MKFOsBlMmFS5wnBk8jr" : {
"coverImg" : "https://firebasestorage.googleapis.com/v0/b/onebidup.appspot.com/o/images%2FcoverImages%2Fa7247e86-b745-4806-8e93-1de733e4f698.jpg?alt=media&token=4b0adf1c-9a90-4da7-9c43-5db40d80ee76",
"description" : "Splendidamente progettato e costruito per durare - elegante, pratico e affidabile",
"name" : "Segway-Ninebot ES4 Monopattino Elettrico",
"price" : "773"
},
"-MKFPAewl96EKp3noj2J" : {
"coverImg" : "https://firebasestorage.googleapis.com/v0/b/onebidup.appspot.com/o/images%2FcoverImages%2F1943a11f-d1ee-4188-9aa9-af0d42466d11.jpg?alt=media&token=f6e1f9ae-7632-406e-acde-5554c45d5ee4",
"description" : "Sony PS4 PRO PlayStation Gamma Chassis + PS Live Card 20€, 4K HDR, 1 TB [Esclusiva Amazon.it]",
"name" : "Sony PS4 PRO PlayStation",
"price" : "419"
},
"-MKFPY6pWSPGUfTGIUuH" : {
"coverImg" : "https://firebasestorage.googleapis.com/v0/b/onebidup.appspot.com/o/images%2FcoverImages%2F0fccd324-e03e-4680-8553-688dd1be25bc.jpg?alt=media&token=c695e0af-d2d2-448e-9747-1aaa6910197f",
"description" : "iRobot Roomba 981 Robot aspirapolvere WiFi, Power-Lifting, 2 spazzole in gomma multi-superficie, Adatto per peli, Tecnologia Dirt Detect, pulizia a 3 fasi, programmabile con app, Compatibile Alexa",
"name" : "iRobot Roomba 981",
"price" : "538.80"
}
}
答案 0 :(得分:1)
问题在于products
是一个空数组,即使在您调用之后:
setProducts([...products, snapshot.val()])
要基于先前的值,您必须使用回调变量:
setProducts(products => [...products, snapshot.val()])
主要问题是setProducts
在下一次渲染时更新products
。它不会影响products
的当前值。通过使用回调,新值将传入并可以使用。
useState
文档中对此行为进行了描述:
功能更新
如果使用先前状态计算了新状态,则可以将函数传递给
setState
。该函数将接收先前的值,并返回更新的值。这是同时使用setState
两种形式的计数器组件的示例:function Counter({initialCount}) { const [count, setCount] = useState(initialCount); return ( <> Count: {count} <button onClick={() => setCount(initialCount)}>Reset</button> <button onClick={() => setCount(prevCount => prevCount - 1)}>-</button> <button onClick={() => setCount(prevCount => prevCount + 1)}>+</button> </> ); }
“ +”和“-”按钮使用功能形式,因为更新后的值基于先前的值。但是“重置”按钮使用常规形式,因为它始终将计数设置回初始值。
如果您的更新函数返回的值与当前状态完全相同,则随后的重新渲染将被完全跳过。