Set a default font globally in React Native project - react-native

I've set up and added a set of fonts under /assest/fonts/, created react-neative.config.js and linked these accordingly.
I can call the custom font in my styles but haven't been able to initialize a global setting for it.
Trying to do this through a component, like so
import React from 'react';
import { Text } from 'react-native';
export default props => <Text {...props} style={[{ fontFamily: 'Roboto-Regular' }, props.style]}>{props.children}</Text>
Then importing this either via App.js or a page component etc by calling CustomFont.
This doesn't render the font though (I'm stuck with the OS default or whatever style has been applied for that particular element). Any ideas?

I think that the problem here is that you inversed the order in the style object. You should assign to the style all the properties of props.style and then apply on them your custom font
import React from 'react';
import { Text } from 'react-native';
export default props => <Text {...props} style={{...props.style, fontFamily: 'Roboto-Regular'}}>{props.children}</Text>

Please correct assest to assets.
module.exports = {
assets: ['./assets/fonts']
}

Related

Tailwind - how to set default text color in React Native

Im building a project in react native and tailwind. For every text component, I am passing "text-black".
<Text style={tailwind('text-black')}> Hi </Text>
Can I set the default color for text component to be black somewhere to overcome this problem ?
You'll want to create a custom component that wraps the Text component and applies the default style you want.
import React from 'react';
import { Text } from 'react-native';
const DefaultText = ({ style, children }) => (
<Text style={[tailwind('text-black'), style]}>{children}</Text>
);
export default DefaultText;
Now, whenever you want to use a Text component and have it automatically be styled with the default color, just use the DefaultText component instead.

How can I toggle a dark theme for a stack of screens?

I have included a snack expo here that reproduces the exact layout of my project. App.js -> stack of screens. I am trying to figure out the best way to toggle between light theme and dark theme. I do not care for the ios dark theme setting to trigger this, for now, I just want the button to trigger it.
I would like there to be a button displayed on my home screen that when pushed toggles to the theme it is not currently on. I originally wanted to use theme provider to set my colors for each theme and then call that color on each page rather than the hard coded color but have failed to do so.
When you have a stack of screens being called in a tab navigator, what is the best way to use a dark theme?
You need to use the theme prop of the NavigationContainer but your are still responsible for providing the styling for each of your components.
That said, there are a couple of things we need to do here.
Let the button change the theme prop of the NavigationContainer.
Provide a custom styling (colors etc.) for all of your components depending of the theme.
We can solve the first problem by wrapping the NavigationContainer into a ContextProvider as follows.
import React, {useState} from 'react';
import {
DefaultTheme,
DarkTheme,
NavigationContainer,
} from '#react-navigation/native';
export const ThemeContext = React.createContext();
export default function App() {
const [theme, setTheme] = useState(DefaultTheme)
return (
<ThemeContext.Provider value={{theme, setTheme}}>
<NavigationContainer theme={theme}>
</NavigationContainer>
</ThemeContext.Provider>
);
}
In your Toggle component you can then change the theme dynamically as follows.
import {ThemeContext} from '../App'
import {
DefaultTheme,
DarkTheme,
} from '#react-navigation/native';
const Toggle = (props) => {
const { setTheme, theme } = React.useContext(ThemeContext);
return (
<TouchableOpacity onPress={() => setTheme(theme === DefaultTheme ? DarkTheme : DefaultTheme)}>
</TouchableOpacity>
);
}
You will notice that changing the theme will not change anything in your current setup. This is because you need to take care of this yourself.
This could be done using either the context again or the useTheme hook. For your HomeScreen this could be done as follows.
import { useTheme } from '#react-navigation/native';
const Home = () => {
const { colors } = useTheme();
return (
<View style={{justifyContent: 'center', alignItems: 'center', flex: 1, backgroundColor: colors.background}}>
<Toggle/>
<Screen/>
</View>
);
}
Toggling the button changes the theme now. You can access the default theme colors using the useTheme hook but you still need to apply it to your components. You could also provide a custom theme which is done similar.
I would suggest doing something similar to this:
https://www.section.io/engineering-education/how-to-control-dark-mode-in-react-native-using-redux/.
In the article the author uses React Native Paper to control what each of his screens look like. I personally have a theme.js file that has an if statement based on what my Redux state is set to. If it is to light mode, my global theme variables (e.g. background color, text color, etc.) are set to their respective light colors. When set to dark mode, my global theme variables are set to their respective dark colors.

React Native "undefined is not an Object"

Code:
import { ImageBackground,StyleSheet } from 'react-native';
function WelcomeScreen(props) {
return (
<ImageBackground
style={styles.background}
source={require("../assets/background.jpg")}
></ImageBackground>
);
}
const styles = StyleSheet.create({
background:{
flex: 1
}
});
export default WelcomeScreen;
Output:
To explain why:
import * as React from 'react';
fixed your problem...
You are not using just plain JavaScript in this file.
Anything that looks like a HTML tag e.g. <ImageBackground> is JSX and needs to be transpiled to plain JavaScript by babel (or some other transpiler).
Your transpiler needs use the React library for JSX and therefore any files using JSX require this import.

Type Error: undefined is not an object React-Native

I'm trying to style a View in React-native but I keep getting this Error
(undefined is not an object (evaluating 'styles.screen))
I made a simple code ...
import React, {useState} from 'react';
import {StyleSheet, Text, View, Button, TextInput} from 'react-native';
export default function App() {
return (
<View style={styles.screen}>
<Text>I am testing</Text>
</View>
);
const styles = StyleSheet.create({
screen: {
padding: 50,
},
});
}
I spent two hours trying to fix this
This should fix it:
import React, { useState } from 'react';
import { StyleSheet, Text, View, Button, TextInput } from 'react-native';
export default function App() {
return (
<View style={styles.screen}>
<Text>I am testing</Text>
</View>
);
}
const styles = StyleSheet.create({
screen: {
padding: 50,
},
});
You need to move the const styles object outside of your App() function. The way you have it will return before initialising your stylesheet. An alternative is to place it before your return() inside App() but it is more standard to have it outside.
So, after troubleshooting for 3 hours and finding no info on this, I finally have the answer. I used a class template search bar React Native Search Bar and created custom styles for said search bar that was being exported from a file, in a folder named 'components' in a parent folder 'app' that was in my '[project]' folder. I imported the class to each screen as it was a header.
The following was an *incorrect import:
import {SearchComponent} from './app/components/searchComponent'
The correct import is:
import SearchComponent from './app/components/searchComponent'
(Because the SearchComponent was exported as a default component and not a named component in the searchComponent.js file.)
Quick reference to default vs named exports
After correctly importing the component, make sure your styles within that component's folder are named correctly and do not share style names with other styles in your destination file; i.e., name of fileA:styleA != name of fileB:styleA.
After checking your exports and imports very, very carefully and checking your style names with the same detail it worked – and it should work for you, as well.

How to create and connect a custom component theme for Native Base

I'm using Native Base 2.0+, the themes are ejected and using StyleProvider I am able to tweak and customize any Native Base component according to my theme, no problem.
Following the docs, it's stated that to add themes to a custom component we should define a namespace for said component and merge it with the instantiated styling as well. Code example below:
import React, { Component } from 'react'
import { Header, Left, Body, Right, Button, Title, Text, connectStyle } from 'native-base'
import Colors from '../Themes/Colors'
import ApplicationStyles from '../Themes/ApplicationStyles'
class NBHeader extends Component {
render () {
const styles = this.props.style
return (
<Header style={styles.header}>
<Left>
<Button transparent>
<Text style={styles.headerBackButton}>
{'< Back'}
</Text>
</Button>
</Left>
<Body>
<Title>Login</Title>
</Body>
<Right />
</Header>
)
}
}
export default connectStyle('CustomComponents.Header', ApplicationStyles)(NBHeader)
In this case, namespace for the component is 'CustomComponents.Header'. Then, we use StyleProvider to connect the Theme:
import React, { Component } from 'react';
import { StyleProvider } from 'native-base';
class CustomComponent extends Component {
render() {
return (
// connect styles to props.style defined by the theme
const styles = this.props.style;
<StyleProvider style={customTheme}>
Your Custom Components
</StyleProvider>
);
}
}
// Define your own Custom theme
const customTheme = {
'yourTheme.CustomComponent': {
// overrides CustomComponent style...
}
};
Since I've ejected the theme, I entered the new namespace for the Custom Component in NB's Theme file, so it should already be added and cascaded using StyleProvider.
So for instance, if I want the header to be 'red' and have a padding of '10' due to theming rules, I add those as default props of 'CustomComponents.Header' and forget about it, it will always be applied to the component as long as the StyleProvider is cascading themes.
The problem is I cannot get this defined Custom Component's default theme to be applied. I don't know if it's a problem with my code or how Native Base works. Any help would be appreciated and I can provide further code if needed.