[英]How do I load firebase data into react-redux asynchronously?
I am currently trying to load my product data into redux, but so far I cant seem to pass the product information returned from firestore into the reducer.我目前正在尝试将我的产品数据加载到 redux 中,但到目前为止,我似乎无法将从 firestore 返回的产品信息传递到 reducer 中。
Index.js -> load first 10 products from firestore soon after store was created. Index.js -> 在创建商店后立即从 firestore 加载前 10 个产品。
store.dispatch(getAllProducts)
action/index.js动作/index.js
import shop from '../api/shop'
const receiveProducts = products => ({
type: types.RECEIVE_PRODUCTS
products
})
const getAllProducts = () => dispatch => {
shop.getProducts(products => {
dispatch(receiveProducts)
})
}
shop.js商店.js
import fetchProducts from './firebase/fetchProducts'
export default {
getProducts: (cb) => cb(fetchProducts())
}
fetchProducts.js fetchProducts.js文件
const fetchProducts = async() => {
const ProductList = await firebase_product.firestore()
.collection('store_products').limit(10)
ProductList.get().then((querySnapshot) => {
const tempDoc = querySnapshot.docs.map((doc) => {
return { id: doc.id, ...doc.data() }
})
}).catch(function (error) {
console.log('Error getting Documents: ', error)
})
}
In product reducers在产品减速器中
const byId = (state={}, action) => {
case RECEIVE_PRODUCTS:
console.log(action); <- this should be products, but it is now promise due to aysnc function return?
}
I can get the documents with no issues (tempDocs gets the first 10 documents without any issue.) but I am not able to pass the data back into my redux. If I were creating normal react app, I would add a loading state when retrieving the documents from firestore, do I need to do something similar in redux as well?我可以毫无问题地获取文档(tempDocs 毫无问题地获取前 10 个文档。)但我无法将数据传回我的 redux。如果我正在创建普通的 React 应用程序,我会在检索时添加加载 state来自 firestore 的文件,我是否也需要在 redux 中做类似的事情?
Sorry if the code seems messy at the moment.抱歉,如果代码目前看起来很乱。
fetchProducts
is an async function so you need to wait for its result before calling dispatch
. fetchProducts
是一个异步 function 所以你需要在调用dispatch
之前等待它的结果。 There are a few ways you could do this, you could give fetchProducts
access to dispatch
via a hook or passing dispatch to fetchProducts
directly.有几种方法可以做到这一点,您可以让
fetchProducts
通过钩子访问dispatch
或直接将 dispatch 传递给fetchProducts
。
I don't quite understand the purpose of shop.js
but you also could await
fetchProducts
and then pass the result of that into dispatch.我不太了解
shop.js
的用途,但您也可以await
fetchProducts
,然后将其结果传递给 dispatch。
A generalized routine I use to accomplish exactly this:我用来完成这个的通用例程:
const ListenGenerator = (sliceName, tableName, filterArray) => {
return () => {
//returns a listener function
try {
const unsubscribe = ListenCollectionGroupQuery(
tableName,
filterArray,
(listenResults) => {
store.dispatch(
genericReduxAction(sliceName, tableName, listenResults)
);
},
(err) => {
console.log(
err + ` ListenGenerator listener ${sliceName} ${tableName} err`
);
}
);
//The unsubscribe function to be returned includes clearing
// Redux entry
const unsubscriber = () => {
//effectively a closure
unsubscribe();
store.dispatch(genericReduxAction(sliceName, tableName, null));
};
return unsubscriber;
} catch (err) {
console.log(
`failed:ListenGenerator ${sliceName} ${tableName} err: ${err}`
);
}
};
};
The ListenCollectionGroupQuery
does what it sounds like; ListenCollectionGroupQuery
听起来像; it takes a tableName
, an array of filter/.where() conditions, and data/err callbacks.它需要一个
tableName
,一个 filter/.where() 条件数组和 data/err 回调。
The genericReduxAction
pretty much just concatenates the sliceName and TableName to create an action type (my reducers de-construct action types similarly). genericReduxAction
几乎只是连接 sliceName 和 TableName 来创建一个动作类型(我的缩减器以类似的方式解构动作类型)。 The point is you can put the dispatch into the datacallback.重点是您可以将分派放入数据回调中。
Beyond this, you simply treat Redux as Redux - subscribe, get, etc just as if the data were completely local.除此之外,您只需将 Redux 视为 Redux - 订阅、获取等,就好像数据完全是本地的一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.