无法访问 React useEffect 中数组的方法和 属性
Cant access to method and property of an array inside React useEffect
我正在为我的项目使用 Firebase、React、Redux,我想使用 useEffect() 将数据从 firebase 发送到 redux 的全局存储。我面临的问题是我无法访问数组的方法和属性,即使我可以使用 console.log(array)
来获取它的元素。
让我简要解释一下我的代码:
我将从数据库中获取的每组 images
分配给各自的 product
,然后将其发送到 redux 全局存储。
我的 Firebase 结构:
products --> images
products
是根集合,images
是 products
的子集合
在我的 useEffect() 中,我定义了 3 个函数,它们是 extractImagesFromDatabase
、getOtherDataAndSendGlobalStore
和 SendDataToGlobalStore
。我使用 2 个函数从数据库中检索数据的原因是 extractImagesFromDatabase
仅从 products/productsId/images
获取数据,而 getOtherDataAndSendGlobalStore
从 products
集合获取数据。
正如他们的名字所暗示的那样,
extractImagesFromDatabase
的作用是从数据库中获取图片,
getOtherDataAndSendGlobalStore
的作用是从数据库中获取其他数据,
SendDataToGlobalStore
是一个调用上面两个函数的函数。
在使用 extractImagesFromDatabase
函数获取“图像”后,我将它们推送到数组“图像”,稍后我想在 getOtherDataAndSendGlobalStore
函数中使用它。
在使用 getOtherDataAndSendGlobalStore
从数据库中获取我想要的所有数据后,我使用名为 setProducts
的操作将这些数据与“图像”数组一起发送到 redux 全局存储。
let images = [];
//load products and make it app wide
useEffect( () => {
function extractImagesFromDatabase() {
db.collection("products").orderBy('timestamp', 'desc').onSnapshot(dataSnapshot => {
// extract images and push them to images for later storage into global store
dataSnapshot.docs.map(doc => {
db.collection("products").doc(doc.id).collection("images").onSnapshot(imagesSnapshot => {
images.push(imagesSnapshot.docs.map(doc => doc.data().image))
})
})
})
}
console.log(Array.isArray(images)) // Output --> true
console.log(images) // Output --> []
// > 0: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3a900297-dbfc-4582-9d23-2039d9c46d6c", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=a465979b-9981-4ec1-a2ce-1295e3af7949", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=c9b52990-cb5c-4f99-b7c1-c1fb1644ab7f", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=f23e6056-c7f2-43d0-b45b-f3b4cd212556", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=b7e95f00-a976-4627-b83c-e6f8f2d3ec0d", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3eda6895-4fec-48e3-b8c2-e81d666672ac"]
// > 1: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=02c4a6df-e9d2-4890-ac0c-d4357c80d4d9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=baa5ff66-b2e9-4219-ab9b-5a01eb912656", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=75418f82-d210-4a71-bf1d-fd7f4840b901", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=e656dca8-c9b1-4a94-a2d4-e93d1d35b43a", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=66308ebe-7125-4d27-a18f-46f98cc421a9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=2ffc3372-6b02-44db-8f42-3c1c2d9fb9d9"]
// length: 2
// __proto__: Array(0)
console.log(images.map(image => image)) // Output --> []
console.log(images.length) // Output --> 0
function getOtherDataAndSendGlobalStore() {
images.forEach(image => {
db.collection("products").orderBy('timestamp', 'desc').onSnapshot(dataSnapshot => {
// push products data including images to global store
setProducts( dataSnapshot.docs.map((doc) => ({
product: {
id: doc.id,
name: doc.data().name,
price: doc.data().price,
description: doc.data().description,
images: image
}
})
))
})
})
}
async function SendDataToGlobalStore() {
await extractImagesFromDatabase();
getOtherDataAndSendGlobalStore()
}
SendDataToGlobalStore()
}, []);
问题是我不能为我在顶部定义的“images”数组使用“forEach”、“map”甚至“length”。但是,当我使用 console.log(images)
检查它是否为空时,我得到了 2 个元素。
Output --> []
// > 0: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3a900297-dbfc-4582-9d23-2039d9c46d6c", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=a465979b-9981-4ec1-a2ce-1295e3af7949", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=c9b52990-cb5c-4f99-b7c1-c1fb1644ab7f", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=f23e6056-c7f2-43d0-b45b-f3b4cd212556", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=b7e95f00-a976-4627-b83c-e6f8f2d3ec0d", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3eda6895-4fec-48e3-b8c2-e81d666672ac"]
// > 1: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=02c4a6df-e9d2-4890-ac0c-d4357c80d4d9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=baa5ff66-b2e9-4219-ab9b-5a01eb912656", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=75418f82-d210-4a71-bf1d-fd7f4840b901", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=e656dca8-c9b1-4a94-a2d4-e93d1d35b43a", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=66308ebe-7125-4d27-a18f-46f98cc421a9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=2ffc3372-6b02-44db-8f42-3c1c2d9fb9d9"]
// length: 2
// __proto__: Array(0)
我被这个问题困了好几天了。如果有人能指出我的错误,将不胜感激。
这段代码有几个明显的问题:
- 此代码将在每次渲染时 运行,可能会出现数十次
await extractImagesFromDatabase();
不会等待,因为函数 extractImagesFromDatabase 不是异步函数。这是编译器应该警告的语法错误。
如何解决这个问题:
将动作引导至外部函数,即使在外部文件中也是如此。 useEffect 应如下所示:
useEffect( () => {
sendDataToGlobalStore(setProducts)
}, [setProducts]);
sendDataToGlobalStore() 应如下所示:
function SendDataToGlobalStore(setProducts) {
db
.collection("products")
.orderBy('timestamp', 'desc')
.onSnapshot(dataSnapshot => {
dataSnapshot
.docs
.map(doc => {
db
.collection("products")
.doc(doc.id)
.collection("images")
.onSnapshot(imagesSnapshot => {
imagesSnapshot.docs.map(doc => {
const image = doc.data().image
db
.collection("products")
.orderBy('timestamp', 'desc')
.onSnapshot(dataSnapshot => {
setProducts( dataSnapshot.docs.map((doc) => ({
product: {
id: doc.id,
name: doc.data().name,
price: doc.data().price,
description: doc.data().description,
images: image
}
})))
})
})
})
})
})
})
}
当你让一个庞大的函数工作时,考虑通过拆分成单独的函数来简化它,并学习异步..等待和承诺。
我正在为我的项目使用 Firebase、React、Redux,我想使用 useEffect() 将数据从 firebase 发送到 redux 的全局存储。我面临的问题是我无法访问数组的方法和属性,即使我可以使用 console.log(array)
来获取它的元素。
让我简要解释一下我的代码:
我将从数据库中获取的每组 images
分配给各自的 product
,然后将其发送到 redux 全局存储。
我的 Firebase 结构:
products --> images
products
是根集合,images
是 products
在我的 useEffect() 中,我定义了 3 个函数,它们是 extractImagesFromDatabase
、getOtherDataAndSendGlobalStore
和 SendDataToGlobalStore
。我使用 2 个函数从数据库中检索数据的原因是 extractImagesFromDatabase
仅从 products/productsId/images
获取数据,而 getOtherDataAndSendGlobalStore
从 products
集合获取数据。
正如他们的名字所暗示的那样,
extractImagesFromDatabase
的作用是从数据库中获取图片,
getOtherDataAndSendGlobalStore
的作用是从数据库中获取其他数据,
SendDataToGlobalStore
是一个调用上面两个函数的函数。
在使用 extractImagesFromDatabase
函数获取“图像”后,我将它们推送到数组“图像”,稍后我想在 getOtherDataAndSendGlobalStore
函数中使用它。
在使用 getOtherDataAndSendGlobalStore
从数据库中获取我想要的所有数据后,我使用名为 setProducts
的操作将这些数据与“图像”数组一起发送到 redux 全局存储。
let images = [];
//load products and make it app wide
useEffect( () => {
function extractImagesFromDatabase() {
db.collection("products").orderBy('timestamp', 'desc').onSnapshot(dataSnapshot => {
// extract images and push them to images for later storage into global store
dataSnapshot.docs.map(doc => {
db.collection("products").doc(doc.id).collection("images").onSnapshot(imagesSnapshot => {
images.push(imagesSnapshot.docs.map(doc => doc.data().image))
})
})
})
}
console.log(Array.isArray(images)) // Output --> true
console.log(images) // Output --> []
// > 0: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3a900297-dbfc-4582-9d23-2039d9c46d6c", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=a465979b-9981-4ec1-a2ce-1295e3af7949", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=c9b52990-cb5c-4f99-b7c1-c1fb1644ab7f", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=f23e6056-c7f2-43d0-b45b-f3b4cd212556", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=b7e95f00-a976-4627-b83c-e6f8f2d3ec0d", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3eda6895-4fec-48e3-b8c2-e81d666672ac"]
// > 1: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=02c4a6df-e9d2-4890-ac0c-d4357c80d4d9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=baa5ff66-b2e9-4219-ab9b-5a01eb912656", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=75418f82-d210-4a71-bf1d-fd7f4840b901", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=e656dca8-c9b1-4a94-a2d4-e93d1d35b43a", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=66308ebe-7125-4d27-a18f-46f98cc421a9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=2ffc3372-6b02-44db-8f42-3c1c2d9fb9d9"]
// length: 2
// __proto__: Array(0)
console.log(images.map(image => image)) // Output --> []
console.log(images.length) // Output --> 0
function getOtherDataAndSendGlobalStore() {
images.forEach(image => {
db.collection("products").orderBy('timestamp', 'desc').onSnapshot(dataSnapshot => {
// push products data including images to global store
setProducts( dataSnapshot.docs.map((doc) => ({
product: {
id: doc.id,
name: doc.data().name,
price: doc.data().price,
description: doc.data().description,
images: image
}
})
))
})
})
}
async function SendDataToGlobalStore() {
await extractImagesFromDatabase();
getOtherDataAndSendGlobalStore()
}
SendDataToGlobalStore()
}, []);
问题是我不能为我在顶部定义的“images”数组使用“forEach”、“map”甚至“length”。但是,当我使用 console.log(images)
检查它是否为空时,我得到了 2 个元素。
Output --> []
// > 0: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3a900297-dbfc-4582-9d23-2039d9c46d6c", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=a465979b-9981-4ec1-a2ce-1295e3af7949", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=c9b52990-cb5c-4f99-b7c1-c1fb1644ab7f", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=f23e6056-c7f2-43d0-b45b-f3b4cd212556", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=b7e95f00-a976-4627-b83c-e6f8f2d3ec0d", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=3eda6895-4fec-48e3-b8c2-e81d666672ac"]
// > 1: (6) ["https://firebasestorage.googleapis.com/v0/b/secret…=media&token=02c4a6df-e9d2-4890-ac0c-d4357c80d4d9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=baa5ff66-b2e9-4219-ab9b-5a01eb912656", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=75418f82-d210-4a71-bf1d-fd7f4840b901", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=e656dca8-c9b1-4a94-a2d4-e93d1d35b43a", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=66308ebe-7125-4d27-a18f-46f98cc421a9", "https://firebasestorage.googleapis.com/v0/b/secret…=media&token=2ffc3372-6b02-44db-8f42-3c1c2d9fb9d9"]
// length: 2
// __proto__: Array(0)
我被这个问题困了好几天了。如果有人能指出我的错误,将不胜感激。
这段代码有几个明显的问题:
- 此代码将在每次渲染时 运行,可能会出现数十次
await extractImagesFromDatabase();
不会等待,因为函数 extractImagesFromDatabase 不是异步函数。这是编译器应该警告的语法错误。
如何解决这个问题:
将动作引导至外部函数,即使在外部文件中也是如此。 useEffect 应如下所示:
useEffect( () => { sendDataToGlobalStore(setProducts) }, [setProducts]);
sendDataToGlobalStore() 应如下所示:
function SendDataToGlobalStore(setProducts) { db .collection("products") .orderBy('timestamp', 'desc') .onSnapshot(dataSnapshot => { dataSnapshot .docs .map(doc => { db .collection("products") .doc(doc.id) .collection("images") .onSnapshot(imagesSnapshot => { imagesSnapshot.docs.map(doc => { const image = doc.data().image db .collection("products") .orderBy('timestamp', 'desc') .onSnapshot(dataSnapshot => { setProducts( dataSnapshot.docs.map((doc) => ({ product: { id: doc.id, name: doc.data().name, price: doc.data().price, description: doc.data().description, images: image } }))) }) }) }) }) }) }) }
当你让一个庞大的函数工作时,考虑通过拆分成单独的函数来简化它,并学习异步..等待和承诺。