首页 > 解决方案 > 如果缓存数据与新的 reducers 结构不一致,我们如何防止移动应用程序崩溃?

问题描述

我目前正在使用 React Native 和 Redux 开发电子商务管理移动应用程序。我们使用 redux-persist 持久化数据。这带来了缓存数据的绝佳体验,这是离线优先开发的原则。

但是在移动世界环境中可能会发生错误。

假设我有一个名为“产品”的减速器。该 reducer 只是一个包含产品对象的数组。用户登录,现在该 reducer 中的数据被持久化。后来,我的开发团队决定在“产品”reducer 上使用新结构更新移动应用程序。用户的应用程序得到更新,现在持久化/缓存的数据与导致应用程序崩溃的新“产品”reducer 结构不一致。

我可能错了,但这是一个可能存在的实际错误吗?如果是这样,什么是解决方法或解决方案?

谢谢!

标签: react-nativecachingmobile-applicationoffline-cachingredux-persist

解决方案


这是一个可能存在的潜在错误,我同意,因为它发生在我身上两次,我发现了一些可能对你有帮助的东西。崩溃的原因取决于存储在磁盘上的内容以及您的代码使用的内容,让我解释一下。

//let say we have a reducer
function ProductReducer(
 state={
       products:[],
       fetching:false
 },action){
   switch(){......}
}


// lets say we have a combine reducer
combineReducers({
   products: ProductReducer
})

//let say we have a component that consums this products
function RenderProducts(){
const {products, fetching} = useSelector((store)=>({
   products: store.products.products,
   fetching: store.products.fetching,
}))
return (
 <View>
  {
    fetching && (
      <Text>
        loading...
      </Text>
      )
   }
     {products.map((item)=>
       <View>
           <Text>
              {item.name}
           </Text>
       </View>)
      }
    </View>
  )
 }

现在我们的更新看起来像这样

// Now lets new reducer be
function ProductReducer(
state={
    productsList:[],
    fetchingProduct:false
},action){
switch(){......}
}

// Now our Render component becomes
function RenderProducts(){
const {products, fetching} = useSelector((store)=>({
  products: store.products.productsList,
  fetching: store.products.fetchingProduct,
 }))
return (
<View>
 {
   fetching && (
     <Text>
       loading...
     </Text>
     )
 }
 {products.map((item)=>
   <View>
       <Text>
          {item.name}
       </Text>
   </View>)
   }
</View>

) }

现在第二个代码将导致崩溃崩溃,原因之一是您将尝试在未定义的对象上调用 .map,为什么会发生这种情况,简单的原因如下所示

// Intial store 
const store = {
  products:{
  products:[], // array of products
  fetching: false,
   }
}

**这是我们作为 JSON 字符串存储在磁盘上的存储 ** 在我们更新到 REDUCER 之后,我们的存储保持不变,在我们从服务器获取数据之前,以便我们的 reducer 可以将我们的更新写入磁盘,渲染产品组件正在尝试应用我们的更新和崩溃

解决方案

  1. 您可以清除商店 // 您不希望这样做,因为包括令牌和重要信息在内的所有存储数据都将丢失,用户将重新启动应用程序

  2. 了解了这个问题后,您现在可以有多种解决方法,例如在渲染组件之前分派一个操作以在磁盘上强制执行迁移。这就是我要应用更新的意思,我会这样做...

     function ProductReducer(
        state={
        productsList:[],
        fetchingProduct:false
     },action){
      switch(action.type){
       case 'MIGRATING':{
      if(store.products){ // checking if products exist on the products 
       reducer this will handle updates and new installs
        state = {...state,productsList: 
          state.products,fetchingProduct:state.fetching}
    
          }
          return state;
        }
      }
     }
    

这会将更改写入磁盘,但请确保在渲染组件之前运行它我将为所有减速器执行此操作

  1. 我将编写我的组件以始终检查他们正在读取的数据是否可用,或者分别为字符串、数组和对象呈现空数据,如 ''、[]、{}

推荐阅读