25

I'm trying to pass props to a component that has been wrapped through a call to create...Navigator call, i.e.

// Search.js
const Navigator = createMaterialTopTabNavigator({
    Wines,
    Stores,
    Vineyards,
    Restaurants
});

// Somewhere in render()...
<Navigator />

I'm trying to figure out how to pass parameters to the Wines / Stores / etc. components from the Search component (above). I've read the docs and apparently this can be done easily with navigation.navigate by passing in an object, but I'm not sure how to do it with this particular method. Can someone please help?

James Ko
  • 32,215
  • 30
  • 128
  • 239
  • Are you trying to make a search screen like instagram? A searchBar and below tabs with different solutions, and you want to pass the search criteria down to tabs? – bennygenel May 20 '18 at 08:52

2 Answers2

22

Based on this you can pass properties to screens also like this:

return (
    <NavigationContainer>
      <Tab.Navigator>
            <Tab.Screen name="Home">
                {(props) => <HomeScreen  {...props} text={homeText} />}
            </Tab.Screen>
           <Tab.Screen name="Settings" component={SettingsScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );

The difference to the following method from the docs

            <Tab.Screen name="Home" component={HomeScreen} />

is this:

            <Tab.Screen name="Home">
                {(props) => <HomeScreen  {...props} text={homeText} />}
            </Tab.Screen>

This worked just fine for me in a similar case.

vindom
  • 459
  • 4
  • 9
21

Your example is a bit vague so I try to explain as much as I can.

There is 2 different ways to pass properties to screens (except redux implementation).

1) navigate action

You can pass parameters to navigated screen with passing params argument to the screen.

navigation.navigate({routeName, params, action, key}) OR navigation.navigate(routeName, params, action)

routeName - A destination routeName that has been registered somewhere in the app's router

params - Params to merge into the destination route

action - (advanced) The sub-action to run in the child router, if the screen is a navigator. See Actions Doc for a full list of supported actions.

key - Optional identifier of what route to navigate to. Navigate back to this route, if it already exists

Sample

this.props.navigate('Profile', { name: 'Brent' })

2) screenProps

You can pass a global parameter to the navigation which can be available in every screen for that navigation.

screenProps - Pass down extra options to child screens

Sample

const SomeStack = createStackNavigator({
  // config
});

<SomeStack
  screenProps={/* this prop will get passed to the screen components as this.props.screenProps */}
/>

I have created a small sample app which I am guessing you are trying to achieve.

const Tab = ({name, searchValue}) => (
  <View style={styles.tabContainer}>
    <Text>{name}</Text>
    <Text>{`Searching: ${searchValue || '...'}`}</Text>
  </View>
);

const Wines = (props) => (<Tab name="Wines Page" searchValue={props.screenProps.searchValue} />);
const Stores = (props) => (<Tab name="Stores Page" searchValue={props.screenProps.searchValue} />);
const Vineyards = (props) => (<Tab name="Vineyards Page" searchValue={props.screenProps.searchValue} />);
const Restaurants = (props) => (<Tab name="Restaurants Page" searchValue={props.screenProps.searchValue} />);

const Navigator = createMaterialTopTabNavigator({
    Wines,
    Stores,
    Vineyards,
    Restaurants
});

export default class App extends Component {
  state = {
    text: ''
  }
  changeText = (text) => {
    this.setState({text})
  }
  clearText = () => {
    this.setState({text: ''})
  }
  render() {
    return (
      <View style={styles.container}>
        <SearchBar
          lightTheme
          value={this.state.text}
          onChangeText={this.changeText}
          onClearText={this.clearText}
          placeholder='Type Here...' />
        <Navigator screenProps={{searchValue: this.state.text}} />
      </View>
    );
  }
}
bennygenel
  • 23,896
  • 6
  • 65
  • 78
  • An alternative is to use Redux to get around React-navigations awful architecture. Or use Wix's React-native-navigation which is much better, has 'passProps'. – Oliver Dixon Oct 02 '18 at 10:38
  • 2
    screenProps has been removed in react-navigation 5 https://github.com/react-navigation/rfcs/pull/5 – Hylle Oct 16 '19 at 13:06