Using React Native StyleSheet like class of HTML - react-native

I had this question a long time ago. What if I use React Native StyleSheet like class of HTML? I really did use it. I have a lot of styles (names are based on Bootstrap Class Name).
import { StyleSheet } from "react-native";
const s = StyleSheet.create({
flex: { flex: 1 },
flexCenter: {
flex: 1,
alignItems: "center",
justifyContent: "center",
paddingVertical: 24,
},
p0: { padding: 0 },
p1: { padding: 4 },
p2: { padding: 8 },
textLight: { color: "#eee" },
fsLg: { fontSize: 18 },
... and so on
});
export default s;
Then, in components I use it like this.
<Text style={[s.fsLg, s.p2, s.textLight]}>Title</Text>
I do not use it anymore because I had a feeling it was a bad practice. I don't know surely. I have read official react native styling. They did not mention this is bad. How do anyone think?

When in doubt, check the docs: https://reactnative.dev/docs/style
The style prop can be a plain old JavaScript object. That's what we usually use for example code. You can also pass an array of styles - the last style in the array has precedence, so you can use this to inherit styles.
From the second paragraph. This is a recommended practice.

Related

Inheritance In React Native Style Sheets

So in a regular cascading style sheet we can inherit from other styles doing so:
.myStyle .temp {
height: 100px,
width: 80px,
}
My question is:
is there a way for me to do this in react native. I have tried a few different ways but cannot seem to get it to work. Some of the methods in which I have tried are as follows:
// Example One
// Error Thrown: tempStyle is not defined.
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
...tempStyle,
},
tempStyle :{
backgroundColor: 'tomato'
}
});
The following also did not work for me, it did not throw any errors but simply did not work.
I set the style to be the tempStyle and it was basically a blank style sheet which does make sense as it probably points to nothing.
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
tempStyle :{
container :{
backgroundColor: 'tomato'
}
}
});
I know that we can reference multiple styles inside of the style property in a component using brackets.
<View style={[Styles.temp, Styles.tempTwo]} />
Is this the only way to accomplish this?
Your first idea does not work because you are trying to use a style object defined inside the create function of StyleSheet for another style object defined within the same create function. You cannot access them inside the create function.
However, you could define your styles in a plain JS object and then use the spread syntax in order to achieve pretty much the same thing.
Notice that a style is just a JS object after all.
Let us call this file styles.js.
// helper, keep local
const tempStyle = {
backgroundColor: 'tomato'
}
// we only want to use this style
// spread syntax works here
export const container = {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
...tempStyle,
}
export SomeOtherStyle = {
...tempStyle,
}
Then, we can use the above styles as usual.
import { container, SomeOtherStyle } from './styles.js'
...
<View style={[container, someOtherStyle]}></View>
Notice that we can make use of typescript here as well (if you are using it in your project).
// helper, keep local
const tempStyle: ViewStyle = {
backgroundColor: 'tomato'
}
// we only want to use this style
// spread syntax works here
export const container: ViewStyle = {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
...tempStyle,
}
export SomeOtherStyle: ViewStyle = {
...tempStyle,
}
Using typescript, you will have autocompletion and typechecking for your styles. Notice as well that there might be different styles for different types of components (e.g. TextStyle).
you can use the array notation:
<View style={[styles.container, styles.tempStyle]} />

React Native: How to separate roles of developer and 'styler'

I'm working on a React Native app (initially only Web) where we need to separate the roles of developer and styler (i.e. the person responsible for styling the app). With traditional HTML development this is easily done through CSS. In other words, the developer assigns IDs and/or classes to HTML elements, allowing the CSS developer to get to work on the CSS files of the code-base.
Is it possible to do something similar in React Native? In other words, can we change the styles of the various elements of the user interface without needing to modify the code that generates the elements?
Yes. I think the style property of view is pretty similar to CSS, you just need to write a styles.js file separate from your view code. Then your "styler" just need to modify style attributes in that file instead of go into the main code.
Something like this:
Your styles.js
const styles = StyleSheet.create({
container: {
flexDirection: 'column',
backgroundColor: Colors.COLOR_BACKGROUND_LIGHT,
paddingBottom: normalize(50)
},
buttonContainer: {
flexDirection: 'column',
alignItems: 'center',
padding: Dimens.contentPadding
},
inputContainer: {
flexDirection: 'row',
height: normalize(30),
borderBottomWidth: 0.5,
alignItems: 'center',
borderBottomColor: Colors.COLOR_LIGHT_GREY,
},
});
Your index.js
import styles from ".....";
.....
.....
render() {
return (
<View style={styles.container}>
...
</View>
)
}
Hope that help ^^

Access to style property and change it

I am new to React-Native. Say I have a styleSheet contains style for a green button:
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#fff',
},
greenB:{
padding: 5,
height: 80,
width: 80,
borderRadius:160,
backgroundColor:'green',
}, ........
And for some reason I need to change that colour in my code.
render(){
....
const {container, greenB}=styles; //Not sure, how else can I define greenB?
greenB.backgroundColor='black';
return (
<View style={styles.container}>
<View style={styles.greenB} >
....
How can I access backgroundColor from greenB and change that?
I'm getting a TypeError "Attempted to assign to readonly property",
which is reasonable cause styles is a const.
tried to read about state management but not sure how to use it in this case.
React Native's StyleSheet.create is used for better performance and clean code, It caches the style ids to reduce the amount of data that goes through the bridge, so that is why you cannot alter it but only use it .
But there're many solutions, You can use simple javascript object and alter the values as you want.
For example:-
let Styles= {
Text:{
color:'blue'
}
}
Styles.Text.color= 'green'
<Text style={Styles.Text} > </Text>
More over, For dynamic styling i recommend using states instead of variables .

Implementing dark mode in React Native sensibly

I'm trying to add dark mode support to my React Native app. I will have a flag in a mobx store mode which will be light or dark as appropriate.
In order to tie this into an existing app, I wanted to, if possible, keep the existing style definitions and only override when needed (rather than rewrite everything to a light and a dark theme).
I came up with a function like the following to return the appropriate styles based on the current mode:
function getStyle(style) {
let ret = [styles[style]];
if (
styles.hasOwnProperty(Store.mode) &&
styles[Store.mode][style] !== "undefined"
) {
ret.push(styles[Store.mode][style]);
}
return ret;
}
The view would be rendered as such:
...
<View style={getStyle("container")}>
<Text style={getStyle("text")}>Some text</Text>
</View>
...
The styles:
const styles = {
dark: {
container: {
backgroundColor: "#000"
},
text: {
color: "#fff"
}
},
container: {
padding: 20,
backgroundColor: "#fff"
},
text: {
fontSize: 18,
color: "#000"
}
};
Now this works, but I'm not sure if it's coming at some performance cost I'm unaware of right now (the use of the function, using a style object instead of StyleSheet.create...), or if there's a much simpler way I can't see for the trees. I'd rather not do a ternary inline on every element either.
I ended up going a slightly different way, in that I'd add extra styles depending on the current mode, e.g.
<View style={[styles.container, theme[Store.mode].container]}>
<Text style={[styles.text, theme[Store.mode].text]}>Some text</Text>
</View>
And then using the theme var to override
const theme = {
light: {},
dark: {
container: {
backgroundColor: "#000"
},
text: {
color: "#fff"
}
}
};
const styles = {
container: {
padding: 20,
backgroundColor: "#fff"
},
text: {
fontSize: 18,
color: "#000"
}
};
I would suggest taking a look at the Context api in ReactJS. It gives a good out of the box solution for maintaining global data around the component tree.
You can use React.createContext() and react-native-paper
This module makes it simple to change the background with just a button. I made a simple example for you.
I made an example link.

React native: Why does stylesheet.create return object with numbers and not styles?

I created styles, but sometimes I cannot use them because they return numbers:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#FFFFFF'
},
moodSliderContainer: {
justifyContent: 'center',
alignItems: 'center',
width: '100%'
},
postListContainer: {
width: '100%',
height: '100%',
paddingBottom: 120
}
});
console.log(styles);
From React Native documentation - StyleSheet:
Performance:
Making a stylesheet from a style object makes it possible to refer to it by ID instead of creating a new style object every time.
It also allows to send the style only once through the bridge. All subsequent uses are going to refer an id (not implemented yet).
If you want to retrieve the actual style object, you can use StyleSheet.flatten(styles.container).
Stylesheet is used to reduce processing time and optimize performance.
The numbers are a reference to the original stylesheet object. You can check that numbers would be unique per stylesheet and there would be no overlap.
Therefore it makes sense to replace them with numbers. It is similar concept to Images path storage in react-native.
Probably for reusability. Consider the number as index in a table. For e.g., in your case, the container styles are stored at 219
BigStylesMap = {
219: {
flex: 1,
backgroundColor: '#FFFFFF'
}
...otherCachedStyles
}
If it finds some other place where similar styles are defined, it can refer to the same object.