【问题标题】:Firebase firestore : Unhandled Rejection (RangeError): Maximum call stack size exceededFirebase firestore:未处理的拒绝(RangeError):超出最大调用堆栈大小
【发布时间】:2020-12-09 04:10:46
【问题描述】:

出于学习目的开始使用 createAsyncThunk,决定使用 firebase firestore 实现购物车,但在我的 react 应用程序中尝试实现分页时遇到了问题。

在初始加载和后续加载(无限加载)期间,我应该如何将最后一个可见状态返回到我的 redux 状态

我基于 redux 教程沙箱中的代码:https://codesandbox.io/s/github/reduxjs/redux-essentials-example-app/tree/checkpoint-3-postRequests/?from-embed,但我没有连接到假 api,而是使用 firebase firestore。

从 firestore 获取产品的代码:ProductSlice.js

const InitialState = {
   products : [],
   status: 'idle',
   error: null,
   last: null, //to hold lastVisible when fetching data from firestore
}

export const fetchProducts = createAsyncThunk(types.RECEIVE_PRODUCTS, async (limit) => {
   const resp = await fire_base_product.firestore()
      .collection(collection_name).orderBy('id').limit(limit)

   let result = resp.get().then((querySnapshot) => {
      const lastVisible = querySnapshot.docs[querySnapshot.docs.length - 1] //how set this to redux state

      const products = querySnapshot.docs.map((doc)=> {
         return { ...doc.data()}
      })

      return { 
         products: products, 
         lastVisible: lastVisible
      };
   })

   return result;
}

我不太确定如何将这个 lastVisible 数据设置回 redux 状态,是否可以通过参考来做到这一点?

#编辑:

尝试将产品列表和最​​后一个可见作为数组返回,并在 createSlice 中分配 lastVisible,如下所述:

const productSlice = createSlice({
   name:'products',
   initialState: 
   reducers: {},
   extraReducers:{
      [fetchProducts.fulfilled]: (state, action) => {
         state.products = state.products.concat(action.payload.products)
         state.last = action.payload.lastVisible // this causes call stack error
      }

   }
});

上面的编码,如果我运行react app会报两个错误,

  1. 尝试将非序列化值分配到 redux 状态

  2. firestore 中超出了最大调用堆栈大小

然后我尝试在创建配置期间添加中间件 serializableCheck,如下所示:

export default configureStore({
   middlleware: getDefaultMiddlleWare({
      serializableCheck: {
         //ignore action type
         ignoredActions : ['RECEIVE_PRODUCTS/fulfilled']
         // ignore path
         ignoredPath: ['products.last']
      }
   }),
   ... // reducer codes
})

即使现在我已经消除了第一个错误,调用堆栈超出仍然存在。有谁知道为什么会这样?如果有任何解决方法,请随时讨论。谢谢。

编辑 2

类似的方法在使用上下文时有效,但在使用 redux 时无效。我是否需要按照Firebase Unhandled error RangeError: Maximum call stack size exceeded 中的建议将 return 包含在 promise 中?

【问题讨论】:

    标签: javascript redux google-cloud-firestore react-redux redux-thunk


    【解决方案1】:

    没有找到保存 lastVisible 的方法,但我找到了一种解决方法,只需将我的 firestore 数据的最后检索 id 保存为 redux 状态即可。

    export const fetchProducts = createAsyncThunk(types.RECEIVE_PRODUCTS, async (limit) => {
       const resp = await fire_base_product.firestore()
          .collection(collection_name).orderBy('id').limit(limit)
    
       let result = resp.get().then((querySnapshot) => {
          var lastVisible = limit - 1; //only keep track of ID so we can avoid saving un-serialize coded
    
          const products = querySnapshot.docs.map((doc)=> {
             return { ...doc.data()}
          })
    
          return { 
             products: products, 
             lastVisible: lastVisible
          };
       })
    
       return result;
    }
    

    在获取额外数据的过程中,我们可以使用 getState() 访问状态,如下所示:

    export const fetchMoreProducts = createAsyncThunk(types.LOAD_MORE_PRODUCTS, async (limit, {getState}) => {
        const last = getState().products.last
    
        var newProducts = await firebase_product.firestore()
            .collection('store_products').orderBy('id')
            .startAfter(last).limit(limit)
    
        const result = newProducts.get().then((querySnapshot) => {
                var lastVisible = last + limit;
    
                const products = querySnapshot.docs.map((doc) => {
                    return { ...doc.data() }
                })
    
                return {
                    products : products, 
                    lastVisible: lastVisible
                }
            })
    
        // return retrieved data from firebase 
        return result
    })
    

    但是这样做,我也可以一起跳过序列化检查配置。不确定这是否是正确的方法,但这就是我让分页工作的方式。如果有其他方法可以解决这个问题,请随时告诉我。

    【讨论】:

      【解决方案2】:

      如果你在 redux store 中存储不可序列化的对象,就会出现这个错误!

      如果您从 firebase 获取一些不可序列化的数据,请在将其存储到 redux 存储之前对其进行序列化!

      const nonSerializable = firestore().collection().doc(uid).get().data();
      // if using this nonSerializable object in reducer, serialized it using JSON.parse(JSON.stringify())
      const serializable = JSON.parse(JSON.stringify(nonSerializable))
      

      【讨论】:

        【解决方案3】:

        你应该保存最后一个可见路径,而不是像这样保存整个数据

        const lastVisible = querySnapshot.docs[querySnapshot.docs.length - 1].ref.path
        

        【讨论】:

          猜你喜欢
          • 2021-01-27
          • 2019-03-04
          • 2018-06-03
          • 2019-01-24
          • 2021-04-06
          • 2018-01-24
          • 2019-05-04
          • 2018-02-06
          相关资源
          最近更新 更多