skip to Main Content

I would like to have a parent component wrapping the screens so I can pass global styles to those components like instead of repeating same global styles in each component. However, Navigator doesn’t accept View or anything with styles inside it.

return (
    <NavigationContainer>
      <Navigator>
        {isAuthenticated ? (
          <>
            <Screen options={{headerShown: false}} name={'TabsNavigation'} component={BottomTabsNavigator}/>
            <Screen options={{headerShown: false}} name={'Home'} component={Home}/>
          </>
        ) : (
          <>
            <Screen options={{headerShown: false}} name={'Login'} component={Login}/>
            <Screen options={{headerShown: false}} name={'Register'} component={Register}/>
          </>
        )}
      </Navigator>
    </NavigationContainer>
  );

How can I achieve this?

EDIT

All my components start like this:

<SafeAreaView style={styles(theme).flex}>
    <ScrollView contentInsetAdjustmentBehavior="automatic">
        <View>
            <Text>Content here</Text>
        </View>
    </ScrollView>
</SafeAreaView>

So instead I want to make it so all my components start like this:

<View>
    <Text>Content here</Text>
</View>

I want to move SafeAreaView and ScrollView to a parent component

2

Answers


  1. NB: After the edit, this answer does not fit the question


    It’s not 100% clear to me what you’re trying to achieve, however, there are many ways to go about using a shared theme.

    • React Navigation has built-in theming for its components, using the theme prop. You can read about how to use the theme prop here: https://reactnavigation.org/docs/themes/

    • You can save and export one or several StyleSheets, and import them wherever you want. Example:

    export const colors = {
      blue: '#02B4F3',
    };
    
    export const textStyles = StyleSheet.create({
      header: {
        fontSize: 24,
        color: colors.blue,
      },
      ...
    });
    
    // etc
    // and then in your component
    
    import { textStyles } from 'styles';
    
    ...
      <Text style={textStyles.header}>Header</Text>
    ...
    
    • You can make functions that return StyleSheets based on the theme. Example:
    export const textStyles = (theme) => StyleSheet.create({
      header: {
        fontSize: 24,
        color: theme === 'light' ? colors.blue : colors.yellow,
      },
    });
    
    • You can use React Context to hold your themes. There are lots of tutorials for this, like this one (which I haven’t tried btw): https://betterprogramming.pub/react-context-api-part-1-dark-theme-3f00666cbacb

    • Using a UI library like react-native-paper or Native Base often includes support for theming, although I wouldn’t encourage using one only for theming, and in general I do not prefer working with these libraries.

    Login or Signup to reply.
  2. After the edit it’s much more clear, thanks! And the answer is very different so I made a new one.

    What you want is called an HOC, for Higher-Order Component. React makes this easy with the children prop. Here’s an example based on your code:

    const ScreenWrapper = ({ children, theme }) => {
      return (
        <SafeAreaView style={styles(theme).flex}>
          <ScrollView contentInsetAdjustmentBehavior="automatic">
            {children}
          </ScrollView>
        </SafeAreaView>
      );
    };
    

    You’d use this in your screens like this:

      <ScreenWrapper>
        <View>
          <Text>Content here</Text>
        </View>
      </ScreenWrapper>
    

    Anything between <ScreenWrapper> and </ScreenWrapper> is passed to the component under the children prop. This pattern should make it easy to achive what you want. This is how most of the React built-in components (like View or Text) work.

    You can read more about this here: https://reactjs.org/docs/jsx-in-depth.html#children-in-jsx

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search