4

I'm currently trying to learn React Native based on this Tutorial: http://www.appcoda.com/react-native-introduction/

While copying most of the Code (small changes in text) I got this error:

Error: Cannot read property 'push' of undefined

This error occurs if I try to push a new Navigator View. Here is the striped down code (full code at the end but thought it's more readable to have just a short version here):

<TouchableHighlight onPress={() => this._rowPressed(eve)} >



    _rowPressed(eve) {
  this.props.navigator.push({
    title: "Property",
    component: SingleEvent,
    passProps: {eve}
  });
}

Maybe somebody can explain me why the this.props.navigator is undefined and how I can use it. I'm sorry for this basic question but I searched a lot and couldn't find a answer to this problem yet. I tryed to .bind(this) to the _rowPressed function and also rewrote everything to a NavigatorIOS View but nothing worked yet.

Would be nice if somebody could explain it to me.

All the best Daniel

Full Error report:

Error: Cannot read property 'push' of undefined
 stack: 
  Dates._rowPressed                                      index.ios.bundle:52051
  Object._createClass.value.React.createElement.onPress  index.ios.bundle:52033
  React.createClass.touchableHandlePress                 index.ios.bundle:41620
  TouchableMixin._performSideEffectsForTransition        index.ios.bundle:39722
  TouchableMixin._receiveSignal                          index.ios.bundle:39640
  TouchableMixin.touchableHandleResponderRelease         index.ios.bundle:39443
  executeDispatch                                        index.ios.bundle:15431
  forEachEventDispatch                                   index.ios.bundle:15419
  Object.executeDispatchesInOrder                        index.ios.bundle:15440
  executeDispatchesAndRelease                            index.ios.bundle:14793
 URL: undefined
 line: undefined
 message: Cannot read property 'push' of undefined

Code Of the Parent View which gets included into the main View via TabBarIOS:

    'use strict';

var React = require('react-native');
var singleEvent = require('./singleEvent');
var REQUEST_URL = 'http://***/dates/24-09-2015.json';



var {
    Image,
    StyleSheet,
    Text,
    View,
    Component,
    ListView,
    NavigatorIOS,
    TouchableHighlight,
    TabBarIOS,
    ActivityIndicatorIOS
} = React;


var styles = StyleSheet.create({
    container: {
        flex: 1,
        flexDirection: 'row',
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#F5FCFF',
        padding: 10
    },
    thumbnail: {
        width: 53,
        height: 81,
        marginRight: 10
    },
    rightContainer: {
        flex: 1
    },
    title: {
        fontSize: 16,
        marginBottom: 8
    },
    author: {
        color: '#656565',
        fontSize: 12
    },
    separator: {
       height: 1,
       backgroundColor: '#dddddd'
   },
   listView: {
       backgroundColor: '#F5FCFF'
   },
   loading: {
       flex: 1,
       alignItems: 'center',
       justifyContent: 'center'
   }   
});

class Dates extends Component {

  constructor(props) {
      super(props);

      this.state = {
        isLoading: true,
        dataSource: new ListView.DataSource({
           rowHasChanged: (row1, row2) => row1 !== row2
        })
      };
    }


    componentDidMount() {
       this.fetchData();
    }

    fetchData() {
       fetch(REQUEST_URL)
       .then((response) => response.json())
       .then((responseData) => {
           this.setState({
               dataSource: this.state.dataSource.cloneWithRows(responseData),
               isLoading: false
           });
       })
       .done();
    }

      render() {
       if (this.state.isLoading) {
           return this.renderLoadingView();
       }

       return (
            <ListView
                dataSource={this.state.dataSource}
                renderRow={this.renderEvent.bind(this)}
                style={styles.listView}
                />
        );
      }  
    renderLoadingView() {
        return (
            <View style={styles.loading}>
                <ActivityIndicatorIOS size='large'/>
                <Text>Loading Events...</Text>
            </View>
        );
    }

    renderEvent(eve) {
       return (
            <TouchableHighlight onPress={() => this._rowPressed(eve).bind(this)}  underlayColor='#dddddd'>
                <View>
                    <View style={styles.container}>
                        <View style={styles.rightContainer}>
                            <Text style={styles.title}>{eve.value.name}</Text>
                            <Text style={styles.author}>{eve.value.location}</Text>
                        </View>
                    </View>
                    <View style={styles.separator} />
                </View>
            </TouchableHighlight>
       );
    }

    _rowPressed(eve) {

      console.log(eve, this.props);

      this.props.navigator.push({
        title: "Property",
        component: SingleEvent,
        passProps: {eve}
      });
    }
}
module.exports = Dates;

Single View which should be included if the ListView was clicked:

'use strict';

var React = require('react-native');

var {
  StyleSheet,
  Text,
  TextInput,
  View,
  TouchableHighlight,
  ActivityIndicatorIOS,
  Image,
  Component
} = React;

var styles = StyleSheet.create({
    description: {
        fontSize: 16,
        backgroundColor: 'white'
    },
    title : {
        fontSize : 22
    },
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
    }
});

class SingleEvent extends Component {
    render() {
        var eve = this.props.eve;
        var description = (typeof eve.value.description !== 'undefined') ? eve.value.description : '';
        return (
            <View style={styles.container}>
                <Text style={styles.title}>{eve.value.name}</Text>
                <Text style={styles.description}>{description}</Text>
            </View>
        );
    }
}

module.exports = SingleEvent;

index.ios.js where all the views get combined:

'use strict';

var React       = require('react-native');
var Dates       = require('./Dates');
//var Eventlist       = require('./eventlist');
var NearYou     = require('./NearYou');

var icons         = [];
icons['place']    = require('image!ic_place_18pt');
icons['reorder']  = require('image!ic_reorder_18pt');
icons['grade']    = require('image!ic_grade_18pt');
icons['people']   = require('image!ic_group_18pt');

var {
    Image,
    AppRegistry,
    StyleSheet,
    Text,
    View,
    ListView, 
    TouchableHighlight,
    TabBarIOS,
    Component
} = React;

class allNightClub extends Component {

    constructor(props) {
        super(props);
        this.state = {
            selectedTab: 'dates'
        };
    }

    render() {
        return (
            <TabBarIOS selectedTab={this.state.selectedTab}>
                <TabBarIOS.Item
                    selected={this.state.selectedTab === 'dates'}
                    icon={icons['reorder']}
                    title= 'Events'
                    onPress={() => {
                        this.setState({
                            selectedTab: 'dates'
                        });
                    }}>
                    <Dates navigator={navigator} />
                </TabBarIOS.Item>
               <TabBarIOS.Item
                    selected={this.state.selectedTab === 'nearyou'}
                    title= 'Favorites'
                    icon={icons['grade']}
                    onPress={() => {
                        this.setState({
                            selectedTab: 'nearyou'
                        });
                    }}>
                    <NearYou navigator={navigator} />
                </TabBarIOS.Item>
                <TabBarIOS.Item
                    selected={this.state.selectedTab === 'nearyou'}
                    title= 'Near You'
                    icon={icons['place']}
                    onPress={() => {
                        this.setState({
                            selectedTab: 'nearyou'
                        });
                    }}>
                    <NearYou navigator={navigator} />
                </TabBarIOS.Item> 
                <TabBarIOS.Item
                    selected={this.state.selectedTab === 'nearyou'}
                    title= 'People'
                    icon={icons['people']}
                    onPress={() => {
                        this.setState({
                            selectedTab: 'nearyou'
                        });
                    }}>
                    <NearYou navigator={navigator} />
                </TabBarIOS.Item> 
            </TabBarIOS>
        );
    }
}

AppRegistry.registerComponent('allNightClub', () => allNightClub);

3 Answers 3

4

in your index.ios.js you're referencing a navigator here which isn't set at that moment.

<Dates navigator={navigator} />

So, as I've understood you have to options to work with NavigatorIOS:

1. NavigatorIOS as a child of your Tab

You need to define a navigator as a child of your TabViewItems which itself loads the appropriate view:

var styles = StyleSheet.create({
    container: {
        flex: 1,
    }
});

<TabBarIOS.Item>
<NavigatorIOS
    style={styles.container}
    initialRoute={{
        title: 'Dates',
        component: Dates,
    }}
/>
</TabBarIOS.Item>

2. NavigatorIOS as the root Element

class allNightClub extends Component {

  render() {
        return (
            <NavigatorIOS
                style={styles.container}
                initialRoute={{
                  title: 'Index',
                  component: Index
                }}
            />
        );
    }
}

That's the way it's worked for me. I put the original code of index.ios.js into Index.js and also did the following changes:

Index.js

<Dates
    navigator={this.props.navigator}
/>

Dates.js

<TouchableHighlight onPress={() => this._rowPressed(eve)}  underlayColor='#dddddd'>
Sign up to request clarification or add additional context in comments.

Comments

1

From what I can deduct, your call to this.props.navigator should work, even without the bind-statements.
My first thoughts would be: is the navigator item passed to your Dates component from its parent?

return (
  <Dates
    navigator={navigator}
    ... />

Probably inside a renderscene function where you render your navigator..

What does your output look like from your console statement?

console.log(eve, this.props)

4 Comments

Thanks for your feedback. I added the navigator- tag to the Dates component and now the log shows Object {navigator: Navigator} but still the view isn't working. The error changed to: Error: this.props.navigator.push is not a function. Maybe you have one more suggestion? Thanks again. Daniel
Hmm, Could you share the code where the Dates component is made? Some lines around the <Dates> function would be helpful. Especially the code where the <navigator> object is made..
Aha, I see the issue: the parent component of Dates is a TabBarIOS. item component. see [link]facebook.github.io/react-native/docs/tabbarios.html for description
In the original tutorial you reference, the Navigator component is added in featured.js, as explained in the "adding a navigation bar".
0

I ran into this issue today, the reason is that you need to call the screen where you're using this.props.navigator.push with the NavigatorIOS component. That will set the navigator prop. E.g.

<NavigatorIOS
    style={styles.container}
    initialRoute={{
    title: '',
    component: DemoScreen
  }}
/>

Now in your DemoScreen you can use this.props.navigator.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.