Redux在React Native应用中的怪异行为

时间:2019-05-07 16:37:40

标签: javascript reactjs react-native redux react-navigation

我最近注意到我想与您分享Redux在我的应用程序中的异常行为。当我在设置中单击此TouchableOpacity以断开连接时,出现以下错误:

  

TypeError:无法读取null的属性first_name

来自Homepage.js

因此,我的代码针对我不应该去的页面中的那个部件触发了错误。

Homepage.js

<AppText textStyle={styles.title}>
  Welcome {userReducer.infos.first_name}
</AppText>

应该执行的工作流程是用户单击断开连接按钮,然后调用tryLogout函数,该函数将触发类型为“ LOGOUT”的操作。然后,此操作将使用一些其他布尔值的用户相关数据和信息设置为空。更新状态后,应重新呈现UI并调用componentWillUpdate()。在其中,我检查自己的状态以将用户重定向到着陆/未连接的导航。

我尝试在我的reducer中注释infos: null,并且我的代码处理没有错误。

该变量在我的应用中无处显示,要求重定向到任何页面。

调试似乎很复杂,因为问题必须比它看起来的更深。无论如何,也许有人已经遇到了类似的问题,所以我在这里为您提供解决该问题的潜在要素。

Settings.js

import { tryLogout } from '@actions/user'

const mapDispatchToProps = dispatch => ({
  tryLogout: () => dispatch(tryLogout()),
})

class Settings extends React.Component<Props, State> {  

  // What should normally happen
  componentDidUpdate(prevProps: Props) {
      const { userReducer, navigation } = this.props

      if (
        prevProps.userReducer.isSignedUp !== userReducer.isSignedUp ||
        prevProps.userReducer.isLoggedIn !== userReducer.isLoggedIn
      ) {
        if (!userReducer.isSignedUp && !userReducer.isLoggedIn) {
          navigation.navigate('Landing')
        }
      }
    }

  // Inside my render() method
  <AppTouchableOpacity
          onPress={() => tryLogout()}
          style={styles.touchableOpacity}
        >
          Disconnect
  </AppTouchableOpacity>
}

actions / user.js

export const tryLogout = (): Function => (dispatch: Function) => {
  const logout = () => ({
    type: LOGOUT,
  })

  dispatch(logout())
}

reducers / user.js

case LOGOUT:
  return {
    ...state,
    data: null,
    infos: null,
    isLoggedIn: false,
    isSignedUp: false,
  }

App.js (我正在使用React Navigation)

const LandingScenes = {
  Welcome: { screen: WelcomeScreen },
  { /* Some other screens */ }
}

const LandingNavigator = createStackNavigator(LandingScenes, {
  initialRouteName: 'Welcome',
  defaultNavigationOptions: {
    header: null,
  },
})

const SecuredScenes = {
  Homepage: { screen: HomepageScreen },
  Settings: { screen: SettingsScreen },
  { /* Some other screens */ }
}
const SecuredNavigator = createStackNavigator(SecuredScenes, {
  initialRouteName: 'Homepage',
  defaultNavigationOptions: {
    header: null,
  },
})

export default createAppContainer(
  createSwitchNavigator(
    {
      Landing: LandingNavigator,
      Secured: SecuredNavigator,
    },
    {
      initialRouteName: 'Landing',
    }
  )
)

2 个答案:

答案 0 :(得分:1)

如果我的理解正确,那么问题是用户退出时预计不会加载Homepage组件,但是会在null上抛出infos错误。由于您使用的是堆栈导航器,因此您的Homepage组件实际上仍可能安装在堆栈中。您将需要处理null中的Homepage情况,或者在导航到Settings的过程中将其从堆栈中删除。

您可以在Navigation lifecycle - Example scenario的文档中找到有关反应导航的生命周期的更多详细信息,重要的部分在此处:

  

我们从主屏幕开始,然后导航到DetailsS​​creen。然后,我们使用选项卡栏切换到SettingsScreen并导航到ProfileScreen。完成此一系列操作后,所有4个屏幕均已安装

答案 1 :(得分:1)

当'infos'的值为null时,听起来像是尝试渲染的声音。

这很有意义,因为主屏幕仍位于导航堆栈中的主内存中,这是因为导航至设置时正在使用“导航”方法。

所以这是使用react-navigation而不是redux或redux thunk的结果。

要在您的视图中处理此错误情况,除非定义了信息,否则无法渲染文本。像下面的示例一样,您当然可以显示一个加载程序,或者如果infos是undefined / null,那么什么都可以显示,而不是什么也不显示,甚至是默认消息。

真的,这里的最终答案是重组导航。您可能会考虑使用另一种方法导航到设置页面,该页面将重置堆栈导航器,或者将其保持在视图中,这两者都是理想的选择。

例如,查看replace方法,该方法用于重置导航堆栈,甚至查看switch导航器,后者仅显示一个屏幕(其中一个屏幕可以是堆栈导航器,即多个屏幕)一次,在您的应用程序内的上下文之间创建分隔。

{userReducer.infos && (
     <AppText textStyle={styles.title}>
       Welcome {userReducer.infos.first_name}
     </AppText>
)}