Невозможно прочитать свойство undefined или undefined

Текущее поведение

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

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

main.js (выставочный проект)

import Expo from 'expo';
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { Provider } from 'react-redux';

import store from './store';
import AppWithNavigationState from './helpers/AppNavigator';

class App extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <AppWithNavigationState />
      </Provider>
    );
  }
}

Expo.registerRootComponent(App);

store.js

import { createStore, compose, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { persistStore, autoRehydrate } from 'redux-persist';
import { AsyncStorage } from 'react-native';
import reducers from '../reducers';

const store = createStore(
  reducers,
  {},
  compose(
    applyMiddleware(thunk),
    autoRehydrate()
  )
);

// persistStore(store, { storage: AsyncStorage, whitelist: ['likedJobs'] });

export default store;

помощники / AppNavigator.js

import React from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import { addNavigationHelpers, StackNavigator } from 'react-navigation';

import LoginScreen from '../screens/auth/LoginScreen';
// import HomeScreen from '../screens/HomeScreen'; 
// import HomeRoutes from '../routes/HomeRoutes';
import HomeRoutes from '../helpers/HomeNavigator'; 

export const AppNavigator = StackNavigator({
  Login: { screen: LoginScreen },
  Home: { screen: HomeRoutes }, 
});

const AppWithNavigationState = ({ dispatch, nav }) => (
  <AppNavigator navigation={addNavigationHelpers({ dispatch, state: nav })} />
);

AppWithNavigationState.propTypes = {
  dispatch: PropTypes.func.isRequired,
  nav: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  nav: state.nav,
});

export default connect(mapStateToProps)(AppWithNavigationState);

помощники / homeNavigator

import React from 'react';
import PropTypes from 'prop-types';
// import { connect } from 'react-redux';
import { addNavigationHelpers, TabNavigator } from 'react-navigation';

import CustomerListScreen from '../screens/home/CustomerListScreen'; 
import JobListScreen from '../screens/home/JobListScreen'; 

JobListScreen.navigationOptions = {
  tabBarLabel: 'Jobs', 
  title: "Jobs",
  tabBarIcon: ({ tintColor, focused }) => (
    <Icon
      name='wrench'
      size={24}
      style={{ color: tintColor }}
    />
  ),
};

CustomerListScreen.navigationOptions = {
  tabBarLabel: 'Clients', 
  tabBarIcon: ({ tintColor, focused }) => (
    <Icon
      name='users'
      size={24}
      style={{ color: tintColor }}
    />
  ),
};


export const HomeNavigator = TabNavigator({
  Jobs: { 
    screen: JobListScreen, 
   },
  Clients: { 
    screen: CustomerListScreen, 
  } 
});

const HomeNavigationTab = ({ dispatch, nav }) => (
  <HomeNavigator navigation={addNavigationHelpers({ dispatch, state: nav })} />
);

HomeNavigationTab.propTypes = {
  dispatch: PropTypes.func.isRequired,
  nav: PropTypes.object.isRequired,
};

const mapStateToProps = state => ({
  homeNav: state.nav,
});

export default HomeNavigationTab;
// export default connect(mapStateToProps)(HomeNavigationTab);

Редуктор вкладки домашней страницы

import { NavigationActions, addNavigationHelpers } from 'react-navigation';

import { HomeNavigator } from '../helpers/HomeNavigator';

// Start with two routes: The Main screen, with the Login screen on top.
const firstAction = HomeNavigator.router.getActionForPathAndParams('Jobs');
const tempNavState = HomeNavigator.router.getStateForAction(firstAction);
const secondAction = HomeNavigator.router.getActionForPathAndParams('Clients');

const initialNavState = HomeNavigator.router.getStateForAction(
  secondAction,
  tempNavState
);

function homeTabNav(state = initialNavState, action) {
  let nextState;
  switch (action.type) {
    case 'JOBS': 
      nextState = HomeNavigator.router.getStateForAction(
        NavigationActions.navigate({ routeName: 'Jobs' }),
        state
      );
      break;
    case 'CLIENTS':
      nextState = HomeNavigator.router.getStateForAction(
        NavigationActions.navigate({ routeName: 'Clients' }),
        state
      );
      break;
    default:
      nextState = HomeNavigator.router.getStateForAction(action, state);
      break;
  }

  // Simply return the original `state` if `nextState` is null or undefined.
  return nextState || state;
} 

export default homeTabNav;

Редуктор навигации приложений

import { combineReducers } from 'redux';
import { NavigationActions, addNavigationHelpers } from 'react-navigation';

import { AppNavigator } from '../helpers/AppNavigator';

// Start with two routes: The Main screen, with the Login screen on top.
const firstAction = AppNavigator.router.getActionForPathAndParams('Home');
const tempNavState = AppNavigator.router.getStateForAction(firstAction);
const secondAction = AppNavigator.router.getActionForPathAndParams('Login');

const initialNavState = AppNavigator.router.getStateForAction(
  secondAction,
  tempNavState
);

function nav(state = initialNavState, action) {
  let nextState;
  switch (action.type) {
    case 'NAV_LOGIN_SUCCESS': 
      nextState = AppNavigator.router.getStateForAction(
        NavigationActions.back(),
        state
      );
      break;
    case 'LOGOUT':
      nextState = AppNavigator.router.getStateForAction(
        NavigationActions.navigate({ routeName: 'Login' }),
        state
      );
      break;
    default:
      nextState = AppNavigator.router.getStateForAction(action, state);
      break;
  }

  // Simply return the original `state` if `nextState` is null or undefined.
  return nextState || state;
} 

export default nav;

Моя среда

"dependencies": {
    "axios": "^0.16.2",
    "expo": "17.0.0",
    "native-base": "^2.1.5",
    "react": "16.0.0-alpha.6",
    "react-native": "https://github.com/expo/react-native/archive/sdk-17.0.0.tar.gz",
    "react-native-easy-grid": "^0.1.13", 
    "react-native-vector-icons": "^4.2.0",
    "react-navigation": "^1.0.0-beta.11",
    "react-redux": "^5.0.5",
    "redux": "^3.7.0",
    "redux-persist": "^4.8.0",
    "redux-thunk": "^2.2.0"
}

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

обновление 1

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

Warning: Failed prop type: The prop `dispatch` is marked as required in `HomeNavigationTab`, but its value is `undefined`.

person ODelibalta    schedule 18.06.2017    source источник
comment
Когда возникает ошибка?   -  person BravoZulu    schedule 18.06.2017
comment
Когда он загружает экран с навигацией по вкладке «Маршрутизатор» (домой) после события щелчка на странице входа   -  person ODelibalta    schedule 18.06.2017
comment
Где находится HomeScreen файл? Судя по вашему описанию, скорее всего, в этом и заключается проблема. Кроме того, выдает ли ошибка имя файла и номер строки?   -  person DonovanM    schedule 18.06.2017
comment
Я предполагаю, что состояние по умолчанию не определено в редукторе. Когда вы получаете сообщение об ошибке типа cannot read property undefined of undefined, это означает, что вы пытаетесь прочитать свойство неопределенного объекта. Причина, по которой это может произойти, заключается в том, что редукторы запускаются один раз перед засеиванием состояния, которое вы планируете визуализировать. Если вы не определите какое-то начальное состояние, вы можете получить такую ​​ошибку. Как выглядят ваши редукторы?   -  person whs.bsmith    schedule 18.06.2017
comment
Спасибо всем за время, потраченное на помощь. Это действительно ценится. Если от этого вам станет легче, значит, уже за полночь, и я все еще пытаюсь это понять. Я обновил файлы в вопросе, а также сам вопрос. благодарю вас !   -  person ODelibalta    schedule 18.06.2017


Ответы (1)


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

import React from 'react';
import PropTypes from 'prop-types';
import { TabNavigator } from 'react-navigation';

import CustomerListScreen from '../screens/home/CustomerListScreen'; 
import JobListScreen from '../screens/home/JobListScreen'; 

JobListScreen.navigationOptions = {
  tabBarLabel: 'Jobs', 
  title: "Jobs",
  tabBarIcon: ({ tintColor, focused }) => (
    <Icon
      name='wrench'
      size={24}
      style={{ color: tintColor }}
    />
  ),
};

CustomerListScreen.navigationOptions = {
  tabBarLabel: 'Clients', 
  tabBarIcon: ({ tintColor, focused }) => (
    <Icon
      name='users'
      size={24}
      style={{ color: tintColor }}
    />
  ),
};

export const HomeNavigator = TabNavigator({
  Jobs: { 
    screen: JobListScreen, 
   },
  Clients: { 
    screen: CustomerListScreen, 
  } 
});
person Mμ.    schedule 18.06.2017
comment
Спасибо за помощь. У меня создалось впечатление, что дочерний компонент навигатора не нужно подключать к redux, потому что он получает это от родителя. Я сделал то, что вы сказали, и ошибка изменилась на There is no route defined for key Login. Must be one of: 'Jobs','Clients', поэтому кажется, что теперь он заботится только о моих дочерних маршрутах и ​​игнорирует то, что я установил для маршрутов навигатора приложений (родительских) - person ODelibalta; 18.06.2017
comment
Я обновил свой ответ. Я считаю, что теперь это должно сработать. - person Mμ.; 19.06.2017