Странное поведение Redux Thunk в приложении React Native - PullRequest
1 голос
/ 07 мая 2019

Недавно я заметил очень странное поведение Redux в моем приложении, которым я хотел бы поделиться с вами. Когда я нажимаю эту TouchableOpacity в моих настройках, чтобы отключиться, я получаю следующую ошибку:

TypeError: Невозможно прочитать свойство first_name of null

с Homepage.js

Итак, мой код выдает ошибку для того компонента, который находится на странице, куда я не должен идти.

Homepage.js

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

Рабочий процесс, который должен произойти, заключается в том, что пользователь нажимает кнопку разъединения, затем вызывается функция tryLogout, которая запускает действие с типом «ВЫХОД». Затем это действие устанавливает в ноль пользовательские данные и информацию с некоторыми дополнительными логическими значениями. Состояние обновляется, затем пользовательский интерфейс должен быть повторно обработан и вызвана componentWillUpdate (). Там я проверяю свое состояние, чтобы перенаправить пользователя на приземляющуюся / не подключенную навигацию.

Я попытался прокомментировать 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>
}

действия / user.js

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

  dispatch(logout())
}

редукторы / 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 ]

1 голос
/ 07 мая 2019

Звучит так, как будто он пытается визуализировать, когда значение 'infos' равно нулю.

Это имеет смысл, поскольку домашний экран все еще находится в основной памяти, в вашем стеке навигации, потому что вы используете метод навигации при переходе к настройкам.

Таким образом, это результат использования реагирующей навигации, а не редукса или редукса.

Чтобы обработать этот случай ошибки с вашей точки зрения, вы не можете отобразить текст, пока не определена информация.Как показано ниже в качестве примера, вы, конечно, можете отобразить загрузчик или что-то еще, если информация не определена / пуста, а не ничего, или даже сообщение по умолчанию.

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

Посмотрите на метод замены, например, он используется для сброса стека навигации, или даже посмотрите на навигатор коммутатора, который сделан, чтобы показать только один экран (где экран может быть навигатором стека, т.е.много экранов), создавая разделение между контекстами в вашем приложении.

{userReducer.infos && (
     <AppText textStyle={styles.title}>
       Welcome {userReducer.infos.first_name}
     </AppText>
)}
1 голос
/ 07 мая 2019

Если я правильно понимаю, проблема в том, что компонент Homepage не должен загружаться при выходе пользователя, но выдает ошибку null на infos. Поскольку вы используете стековый навигатор, вполне вероятно, что ваш компонент домашней страницы все еще монтируется в стеке. Вам нужно будет либо обработать кейс null в вашем Homepage, либо удалить его из стека во время перехода к Settings.

Вы можете найти более подробную информацию о жизненном цикле в реагирующей навигации в их документации здесь: Жизненный цикл навигации - Пример сценария , важная часть которого находится здесь:

Мы начинаем с HomeScreen и переходим к DetailsScreen. Затем мы используем панель вкладок, чтобы переключиться на экран настроек и перейти к профилю экрана. После выполнения этой последовательности операций все 4 экрана смонтированы !

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...