Как мне асинхронно загружать данные firebase в react-redux?

#reactjs #firebase #google-cloud-firestore #react-redux

# #reactjs #firebase #google-облако-firestore #react-redux

Вопрос:

В настоящее время я пытаюсь загрузить данные о своем продукте в redux, но пока, похоже, я не могу передать информацию о продукте, возвращенную из firestore, в редуктор.

Index.js -> загрузите первые 10 товаров из firestore вскоре после создания магазина.

 store.dispatch(getAllProducts)
 

action/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

 import fetchProducts from './firebase/fetchProducts'

export default {
   getProducts: (cb) => cb(fetchProducts())
}
 

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)
   })
}
 

В редукторах продуктов

 const byId = (state={}, action) => {
   case RECEIVE_PRODUCTS: 
      console.log(action); <- this should be products, but it is now promise due to aysnc function return?
}
 

Я могу получить документы без проблем (tempDocs получает первые 10 документов без каких-либо проблем.), Но я не могу передать данные обратно в мой redux. Если бы я создавал обычное приложение react, я бы добавил состояние загрузки при получении документов из firestore, нужно ли мне делать что-то подобное и в redux?

Извините, если на данный момент код кажется беспорядочным.

Комментарии:

1. Я думаю, вам нужно взглянуть на redux-saga https://redux-saga.js.org /

Ответ №1:

fetchProducts это асинхронная функция, поэтому вам нужно дождаться ее результата перед вызовом dispatch . Есть несколько способов, которыми вы могли бы это сделать, вы могли бы предоставить fetchProducts доступ dispatch через перехват или передать отправку fetchProducts напрямую.

Я не совсем понимаю цель shop.js , но вы также можете await fetchProducts , а затем передать результат этого в отправку.

Комментарии:

1. Привет, спасибо за предложение. Итак, я предполагаю, что мне нужно создать промежуточное программное обеспечение для ожидания асинхронной функции? Что-то вроде этого redux.js.org/tutorials/fundamentals/part-6-async-logic

2. «Создать промежуточное программное обеспечение» звучит более формально, чем то, что я предлагаю. Все, что я говорю, это то, что отправка просто должна быть вызвана после получения результатов из firestore. И есть несколько разных мест, где я могу подумать о том, чтобы выполнить это ожидание, которое я предложил выше.

3. У меня это работает! Я не знал, что вы можете отправить результат напрямую. Ценю вашу помощь,

Ответ №2:

Обобщенная процедура, которую я использую для достижения именно этого:

 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}`
      );
    }
  };
};
 

Он ListenCollectionGroupQuery делает то, на что похоже; он принимает a tableName , массив условий filter/.where() и обратные вызовы data/ err .

В genericReduxAction значительной степени просто объединяет имя среза и имя таблицы для создания типа действия (мои редукторы аналогично деконструируют типы действий). Дело в том, что вы можете поместить отправку в обратный вызов данных.

Помимо этого, вы просто обрабатываете Redux как Redux — subscribe, get и т. Д., Как если бы данные были полностью локальными.