Narcis
Narcis

Reputation: 236

Call onPress method from imported UI navbar component

I am building an app that displays jobs and the commute time for each of them. I have a JobsComponent, where I display the jobs. In this component, I have added an icon on the navbar. When the icon is tapped, a MapComponent should be opened. In this map, I want to display a pin for each job.

The problem that I'm facing is that I've defined the icon in my AppNavigator.js and I want to have the onPress() functionality in JobsComponent.js, but I don't know how to do this. What I've tried:

  1. Adding an ({ onPress }) param to navHeaderRight:

    export const navHeaderRight = ({ onPress }) => (/UI component goes here/ )

but with no results.

  1. One other idea I had was to define the onPress() behaviour in AppNavigator.js, but this means importing a lot of stuff (array of jobs, details for each job) to AppNavigator.js, which is not a good design decision from my point of view.

  2. I tried just doing a console.log in navHeaderRight.onPress from JobsComponent to see if it works at all. It doesn't.

This is my AppNavigator.js:

import {TouchableHighlight, Image, View} from 'react-native';
import MapComponent from './MapComponent';

export const navHeaderRight = ({ onPress }) =>
  (
    <View style={{marginRight: 5}}> 
      <TouchableHighlight underlayColor="transparent">
          <Image 
              source={require('../assets/map.png')} 
              style={{height: 40, width: 40}}/>
      </TouchableHighlight>
    </View>
  )


const Navigator = createStackNavigator({
    Jobs: { 
      screen: Jobs,
      navigationOptions: {
            headerRight: navHeaderRight
          }
    },
    MapComponent: { 
      screen: MapComponent,
      navigationOptions: {
        header: null
      } 
    }
//other screens defined in the navigator go here
  });

const AppNavigator = createAppContainer(Navigator);

export default AppNavigator;

And this is my JobsComponent.js. Here, I try to define the onPress() behaviour in componentDidMount().

import {navHeaderRight} from './AppNavigator';

class Jobs extends Component {

componentDidMount() {
        navHeaderRight.onPress = () => {
            this.props.navigation.navigate('MapComponent', {/*other params go here*/})
        }
    }
}

Expected result: when navHeaderRight.onPress is called, the MapComponent should be opened.

**

Actual result: Nothing happens.

**

Any help will be greatly appreciated. :)

Upvotes: 1

Views: 109

Answers (1)

remeus
remeus

Reputation: 2424

You can use React Navigation route parameters to achieve this.

In AppNavigator.js:

import { TouchableHighlight, Image, View } from 'react-native';
import MapComponent from './MapComponent';

const navHeaderRight = (navigation) => {
  const handlePress = navigation.getParam('handlePress', null);
  return (
    <View style={{marginRight: 5}}> 
      <TouchableHighlight
        underlayColor="transparent"
        onPress={handlePress}
      >
        <Image 
          source={require('../assets/map.png')} 
          style={{height: 40, width: 40}}
        />
      </TouchableHighlight>
    </View>
  );
}

const Navigator = createStackNavigator({
  Jobs: { 
    screen: Jobs,
    navigationOptions: ({ navigation }) => ({
      headerRight: navHeaderRight(navigation),
    }),
  },
  MapComponent: { 
    screen: MapComponent,
    navigationOptions: {
      header: null,
    } 
  }
});

const AppNavigator = createAppContainer(Navigator);

export default AppNavigator;

In JobsComponent.js:

class Jobs extends Component {
  componentDidMount() {
    const handlePress = () => console.log('whatever function you want');
    this.props.navigation.setParams({ handlePress });
  }

  // [...]
}

Upvotes: 1

Related Questions