Is there a way to access colours outside of components? It appears that any access to the styles is through hooks. I am using react-native-snackbar that accepts colours but runs through my middle ware so doesn't have any access to a component.
You can import theme.
import theme from './theme';
const { colors } = theme;
The theme object is created as -
export const theme = createTheme({ ... })
Related
Already Wrap my page with
When switch the button, the color of nav bar changes, but not the page content.
I can change the content theme by importing the following files from ant design;
import 'antd/dist/antd.css'; //white mode
//import 'antd/dist/antd.dark.css'; //dark mode
so how to import different css file by click on the switch button?
Thanks.
Create two separate components for darkMode and whiteMode and use conditional rendering with states or context provider with onClick function.
import darkMode styles inside <DarkModeComponent/> and whiteMode styles in <WhiteModeComponent/>.
const [darkmode,setDarkmode]=useState(false)
and onClick function in like below:
function onClick(){ setState (s => !s) };
and in your components:
return ({darkmode ? <DarkModeComponent/> : <WhiteModeComponent/>})
Also, you can use context Provider for handling this state and pass it to child components.like this : context.provider for swithing theme
I've started using RN recently and have been doing some research on the implementation of themes and/or a dark-light mode. Here's roughly how I understand the two main options so far:
Context: Easy setup and can be accessed via hook inside the component that needs it. I count things like the React Navigation themes since that works, in essence, the same way(?)
Styled Components: Essentially just replacing the components with custom ones that access the current theme and that can then be set up to change their props on toggle if needed.
What I don't like about context, is that (the way I understand it) it wouldn't let me access the theme when using a StyleSheet, since that's outside the component. With the styled components on the other hands I'm not sure if I can cover all options inside my custom components, wouldn't I still need some sort of hook in each component anyway?
I was also thinking about just saving the current theme into my Store (in my case Zustand), together with an action that lets me toggle to a dark-mode. But so far, I haven't really seen anyone else do that, is there a downside to doing it that way?
It's not hard to pass context to your stylesheet, it just requires a bit of extra boilerplate. Something like the below:
import ThemeContext from '<path>';
export default () => {
const theme = useContext(ThemeContext);
const stylesWithTheme = styles(theme);
return <Text style={stylesWithTheme.text>Hi</Text>;
}
const styles = theme => StyleSheet.create({
text: {
color: themeStyles.color[theme];
}
});
const themeStyles = {
color: {
dark: '#FFF',
light: '#000',
},
};
I don't think using styled components would be a big departure from the above scheme.
If you did store your theme in state, and define your styles within the body of the component, that could be a savings in boilerplate. It's up to you whether having your styles in the component body is acceptable.
Side note, if you're already using a state manager, I would recommend not mixing it with the Context API without knowing more. It's simpler to have one solution there.
I need to add a custom font to my app. And all the text, including the button title, have to be displayed in the custom font.
How can I achieve this?
I have added custom font in my app. But it needs to provide font family style to every text and can't change the font family of the button title.
These answers seem like they didn't really read your question.. So here's how to use a font globally without the need of specifying it each and every time:
Create a component like so:
import * as React from 'react';
import { Text } from 'react-native';
export default (props) => {
const defaultStyle = { fontFamily: 'Muli', color: '#14181c' };
const incomingStyle = Array.isArray(props.style) ? props.style : [props.style];
return <Text {...props} style={[defaultStyle, ...incomingStyle]} />;
};
Now, everywhere you have
import { Text } from 'react-native',
replace with
import { Text } from 'src/global-components' :)
Usual way of doing this is:
download font families you want
add all the font files you want to an “assets/fonts” folder in the root of your react native project next
add the location of font file in your package.json "assets": ["./assets/fonts/"]
Run react-native link
And you can use it by name convention of your font files.
I want to create via createBottomTabNavigator. It has 5 tabs. Each tab is a StackNavigator.
One of these tabs has a top tab bar. I create the top tab bar via createMaterialTopTabNavigator
But I know tab count after http request. How can I add tab dynamically? The doc says that
There are workarounds if you absolutely need dynamic routes but you can expect some additional complexity
I am confused about this task.
How can I do that?
Related react-navigation issue: https://react-navigation.canny.io/feature-requests/p/dynamic-routes-for-navigators
I think you can create a component that returns a tabNavigator. You can then access props or do whatever you want to dynamically add or remove tabs. Here I am using the latest version of react-navigation.
import React, { Component } from 'react-native';
import { createAppContainer, createMaterialTopTabNavigator } from 'react-navigation';
class DynamicTabs extends Component {
render() {
// I am using a prop here to update the Tabs but you can use state to update
// when the network request has succeeded or failed
const { shouldRenderTab } = this.props;
const TabNavigator = createMaterialTopTabNavigator({
Tab1: Tab1Component,
Tab2: Tab2Component,
// Create a tab here that will display conditionally
...(shouldRenderTab ? { Tab3: Tab3Component } : {}),
});
const ContainedTabNavigator = createAppContainer(TabNavigator);
return <ContainedTabNavigator />;
}
}
export default DynamicTabs;
This is the current solution I am using adapted from the original solution posted on github
If user has selected light-theme, and switches to dark-theme, then all scenes will immediately render to using the dark-theme.
I am using react-native-router-flux if this helps.
Thanks in advance,
Different approaches are possible. One of them is to use React context. Generally it should be used with caution but theming is one of the official examples where it is suitable.
Theming is a good example of when you might want an entire subtree to have access to some piece of information
So the example might look like
class App extends Component {
getChildContext() {
return {theme: { primaryColor: "purple" }};
}
...
}
App.childContextTypes = {
theme: React.PropTypes.object
};
where you set the context for rest of your application and then you use it in your components
class Button extends Component {
render() {
return <TouchableHighlight underlayColor={this.context.theme.primaryColor}>...
}
}
Button.contextTypes = {
theme: React.PropTypes.object
};
If you want to switch theme, you can set context based on your state/props that can be based on user selection.
Currently we are dealing with same questions and therefore we have starting prototyping library called react-native-themeable.
The idea is to use context to store theme and (re)implement RN components so they can replace original components but supports theming.
Example of theme switching you can find in https://github.com/instea/react-native-themeable/blob/master/examples/src/SwitchTheme.js
You can start by creating one JS file containing two objects that have the colors for each theme. Then just use one as a default and if the user picks another theme save it in the database or using local storage and pull the relevant object.
export const theme1 = {
blue: '#fddd',
red: '#ddddd',
buttonColor: '#fff'
}
export const theme2 = {
blue: '#fddd',
red: '#ddddd'
buttonColor: '#fff'
}
Then just import the relevant file:
import * as themes from 'Themes'
const currentTheme = this.props.currentTheme ? this.props.currentTheme : 'theme1'
const styles = StyleSheet.create({
button: {
color: themes[currentTheme].buttonColor
},
})
Wouldn’t it be great if you could import a colors object directly, and modify the object every time you change the theme and have those new colors propagate to the entire app? Then your components wouldn’t need to have any special theme logic. I was able to achieve this using a combination of AsyncStorage, forced app restart, and async module loading.