简体   繁体   English

无法读取未定义的未定义属性

[英]Cannot read property undefined of undefined

Current Behavior 当前行为

I am very new to React and pretty much all this stack. 我对React和所有这些堆栈非常陌生。 What I am trying to accomplish is to implement a tab navigator inside a stack navigator. 我要完成的工作是在堆栈导航器中实现一个标签导航器。 I've done this without Redux using React navigation library but I can not do it when I move my stack navigator to Redux. 我已经使用React导航库在没有Redux的情况下做到了这一点,但是当我将堆栈导航器移到Redux时却做不到。 I've even tried a different navigation library and I keep ending up with that error in the title which is driving me crazy because it does not tell much (or I just do not get it). 我什至尝试了一个不同的导航库,但最终还是以标题中的错误结尾,这使我发疯,因为它告诉的内容不多(或者我只是听不懂)。

I've used the exact Redux example available in the examples repo . 我已经使用了示例repo中提供的确切Redux示例 everything works until I change my home screen (the one after login) to a tab navigator I've created. 一切正常,直到我将主屏幕(登录后的屏幕)更改为我创建的标签导航器为止。

main.js (expo project) 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 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;

helpers/AppNavigator.js 助手/ 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);

helpers/homeNavigator 助手/ 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);

Home tab reducer 主页标签还原器

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;

App navigation reducer 应用导航减速器

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;

My Environment 我的环境

"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"
}

I have no idea what I am doing wrong or if this is a bug (I bet that it is me though) and I could use some light. 我不知道我在做什么错,或者这是否是个错误(我敢打赌这是我的错),我可以使用一些光源。

update 1 更新1

I've taken off redux from my child navigation (home screen tab nav) and now the error statement has changed to the one below. 我已经从子导航(主屏幕标签导航)中删除了redux,现在错误声明已更改为以下内容。

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

Based on the TabNavigator example here you don't actually need to pass in dispatch or nav in the to your component. 根据此处的TabNavigator示例您实际上不需要将调度或导航传入您的组件。 So remove them and export (or export default) HomeNavigator instead. 因此,请删除它们并导出(或导出默认值) 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, 
  } 
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM