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
CodePudding user response:
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
CodePudding user response:
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.