Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to access the react-navgiation inside of a functional component or class component which doesnt have access to this.props.navigation?

Im doing this inside the react native platform using expo.

I want to display the list of items ( ListItems.js) All_Employees_screen.js . These items are being rendered via a functional component, I want to have a onRowPress() handler to so that upon clicking it i can navigate it to another view, but I dont know how to do it on react-navigation ?

Or since the new functional component can be a class component( this would be better ) how can i access the navigation thing inside it ?

enter image description here

AllProperties.js

import _ from 'lodash';
import React, {
  Component
} from 'react';

import {
  Button,
  ListView,
  ScrollView
} from 'react-native';


import ListItem from './ListItem';
import { connect } from 'react-redux';
import { propertiesFetch } from '../../actions';

// import { FormLabel, FormInput } from 'react-native-elements'

class AllPropertiesScreen extends React.Component {

  componentWillMount(){
    this.props.propertiesFetch();
    this.createDataSource(this.props);
  }

// we do this componentWillMount & componentWillReceiveProps (nextProps) thing twice, coz once the component is
// loaded it loads all teh values but when user hits another view like Create property, The Property data still exists
// in the global state object,

// we could move all the  dc dataSource code into componentWillReceiveProps but its actually gonna benefit us
 // if we make sure that we try to build our data source both when the component first loads up
// & when second time  after we go back and forth other compoennts.

  componentWillReceiveProps(nextProps){
    // nextProps are the next set of props that this component will be rendered with
    // this.props is still the old set of props
    this.createDataSource(nextProps);
  }


createDataSource({ properties }){
  const ds = new ListView.DataSource({
        rowHasChanged: (r1, r2) => r1 !== r2
      });
      this.dataSource = ds.cloneWithRows(properties);
}


    static navigationOptions = ({ navigation }) => {
      const {state, setParams} = navigation;
      return {
        title: 'All Emplooyee',
        headerRight: (
          <Button
            title='Add'
            // onPress={() => setParams({ mode: isInfo ? 'none' : 'info'})}
             onPress={() => navigation.navigate('createProperty')
             }
          />
        ),
      };
    };

goBack(){
    console.log('65 - go Back clicked');
}

renderRow(property){
  // console.log('67-AllPropertiesScreen  =', property);
  return <ListItem property={property}
      onPress={() => { console.log('65 - go Back clicked')  }}
    />;
}

  render() {
    console.log('72-AllPropertiesScreen  this.props', this.props );
    return(
        <ListView
          enableEmptySections
          dataSource={this.dataSource}
          renderRow={this.renderRow}
        />
    );
  }
}

const mapStateToProps = state => {
  console.log('83 - AllPropertiesScreen  state. properties', state );
  const properties = _.map(state.properties, (val, uid ) => {
      return { ...val, uid };  //   { shift: 'Monday'}
  });

  return { properties };
};

export default connect(mapStateToProps, {propertiesFetch}) (AllPropertiesScreen);

ListItem.js

import React, { Component } from 'react';
import { Text, TouchableWithoutFeedback, View } from 'react-native';

class ListItem extends Component {

  // onRowPress(){
  //   Actions.employeeEdit({ employee: this.props.employee });
  // }

  render(){
    const { agent_name, cell, address } = this.props.property;
    console.log('14- ListItem ', this.props);

    return (
        <View>
          <CardSection>
            <Text style={styles.titleStyle}>
                name
            </Text>
            <Text style={styles.titleStyle}>
              cell
            </Text>
            <Text style={styles.titleStyle}>
              address
            </Text>
          </CardSection>
      </View>
    );
  }
}

const styles = {
  titleStyle: {
    fontSize: 18,
    paddingLeft: 15
  }
}

export default ListItem;

//

main.js ( this is where I have all the navigation paths hookedup.

class App extends React.Component {
  render() {
    const MainNavigator = TabNavigator({
          // auth: { screen : AuthScreen },
          // review: { screen: ReviewScreen },  
          // signup: { screen : SignupScreen }, 
          followup: { screen: FollowupScreen },               welcome: { screen : WelcomeScreen },
          auth: { screen : AuthScreen },
          signup: { screen : SignupScreen },
          main: {
            screen: TabNavigator ({
              followup: { screen: FollowupScreen },
              map: { screen: MapScreen },
              deck: { screen: DeckScreen },
              settings : {
                screen: StackNavigator ({
                  settings: { screen: SettingsScreen },
                  // settings: { screen: SettingsScreen },
                  UserProfile: { screen: UserProfileScreen },
                  HelpSupport: { screen: HelpSupportScreen },
                  Notifications: { screen: NotificationsScreen },
                  Signout: { screen: SignoutScreen }   // not working, Navigation object not accessible inside the component
                })  //screen: StackNavigator ({
              },
              followup : {
                screen: StackNavigator ({
                  followup: { screen: FollowupScreen },
                  allProperties: { screen: AllPropertiesScreen },
                  createProperty: { screen: PropertyCreateScreen },
                  Red: { screen: RedPriorityScreen },   // not working, Navigation object not accessible inside the component
                  GreyPriority: { screen: GreyPriorityScreen },

                })  //screen: StackNavigator ({
              },
              draw: {
                screen: DrawerNavigator ({
                  drawin: { screen: DrawScreen },
                })  //screen: StackNavigator ({
              }
            }) //screen: TabNavigator
          }
    }, {
      navigationOptions: {
          tabBarVisible: false
      },
      lazy: true
});

return (
  <Provider store={store}>
    <View style={styles.container}>
      <MainNavigator />
    </View>
  </Provider>
);
}
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    // alignItems: 'center',
    justifyContent: 'center',
  },
});

Expo.registerRootComponent(App);

Solution suggested by @Matt but as soon as I put the navigation={this.props.navigation} it complains. undefined is not an object ( evaluating this.props.navigation )

renderRow(property){
  return (
    <ListItem
      property={property}
      navigation={this.props.navigation}
      onPress={() => {
        console.log( '70-on Press  inside renderRow ');
      }}/>
  );
}
like image 585
JP. Avatar asked Dec 24 '22 16:12

JP.


1 Answers

If the component is not a screen you have to import the navigation.

Try this:

import React from 'react';
import { Button } 'react-native';
import { withNavigation } from 'react-navigation';

class MyBackButton extends React.Component {
  render() {
    return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
  }
}

// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);

For more info check out https://reactnavigation.org/docs/connecting-navigation-prop.html

like image 88
Grez.Kev Avatar answered Dec 28 '22 07:12

Grez.Kev