Reputation: 71
I am using hooks to write a react native app. I have problem with using states inside Styles. The background of text container is red, by default and after pressing the Confirm button should be changed to green. At the moment I face error when I use activeBtn as the backgroundColor in style. Please help me to modify my code in correct way.I simplified my code to be more clear as below:
import React, { useState } from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
const DifficultScreen = (props) => {
const [activeBtn, setActiveBtn] = useState("red");
const confirmHandler = () => {
setActiveBtn("green");
};
return (
<View>
<View style={styles.container}>
<Text style={styles.title}>Difficult screen is showing</Text>
</View>
<View>
<TouchableOpacity onPress={confirmHandler} style={styles.btn}>
<Text>Confirm</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: activeBtn,
alignItems: "center",
justifyContent: "center",
width: "100%",
height: 90,
padding: 35,
},
title: {
color: "black",
fontSize: 18,
},
btn: {
color: "black",
padding: "10%",
backgroundColor: "white",
borderRadius: "5px",
alignSelf: "center",
textAlign: "center",
margin: "5%",
},
});
export default DifficultScreen;
Upvotes: 6
Views: 10423
Reputation: 519
Hello I saw this and have a way I get around this for my own convenience, This is what I do
Assuming this is my external style.js file
import { StyleSheet } from 'react-native';
import { setWidth, setHeigth, height } from '../../utils/config';
type StylesProps = string | null | undefined
const styles = (colorScheme: StylesProps) => {
console.log(colorScheme,"in style view")
//Check if app is dark theme
const isDark = colorScheme === 'dark';
const a = StyleSheet.create({
container: {
flex: 1,
height: setHeigth(105),
},
imgBox: {
height: setHeigth(70),
overflow: 'hidden'
},
bgImg: {
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
overflow: 'hidden'
},
headerNote: {
fontSize: setHeigth(4.2),
fontFamily: 'roboto-regular',
fontWeight: '600',
color: isDark ? 'white' : 'black'
}
})
return a
}
export default styles;
Then in my component I use the style this way passing the current state as a parameter
const AppView = () => {
let colorScheme = useColorScheme();
//Check if app is dark theme
const isDark = colorScheme === 'dark';
return (
<View style={[styles(colorScheme).container]}>
<Text style={[tw`pt-6 text-left font-semibold`, styles(colorScheme).headerNote]}>
Some awesome text
</Text>
</View>
);
};
export default AppView;
Upvotes: 3
Reputation: 11
im not sure if this is fine and got no warning from react, yet its working great with my theming. also you can use react hooks like useState and add logic inside this customed hook for style. Im doing useStyle instead of style.ts|js
import { StyleSheet } from 'react-native'
import { useTheme } from 'react-native-elements'
import { RFValue } from 'react-native-responsive-fontsize'
export const useStyle = () => {
const { theme: { colors } }: any = useTheme()
const styles = StyleSheet.create({
container: {
backgroundColor: colors?.text,
height: RFValue(40),
width: RFValue(40),
justifyContent: 'center',
alignItems: 'center',
borderRadius: RFValue(4)
},
})
return {
styles,
iconColor: colors.secondary,
iconSize: RFValue(25)
}
}
Upvotes: 1
Reputation: 371
In your case, where only one CSS property has to be modified by an external state, I'd use the solution provided by Pradeepsinh Sindhav or Jagrati.
If you have to pass multiple parameters that would impact many properties inside your StyleSheet, you could get the styles
object from, per example, a getStyles
function:
import React, { useState } from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
const DifficultScreen = (props) => {
const [activeBtn, setActiveBtn] = useState("red");
const [height, setHeight] = useState(90);
const [padding, setPadding] = useState(20);
const styles = getStyles(activeBtn, height, padding);
const confirmHandler = () => {
setActiveBtn("green");
setHeight(120)
setPadding(35)
};
return (
<View>
<View style={styles.container}>
<Text style={styles.title}>Difficult screen is showing</Text>
</View>
<View>
<TouchableOpacity onPress={confirmHandler} style={styles.btn}>
<Text>Confirm</Text>
</TouchableOpacity>
</View>
</View>
);
};
const getStyles = (buttonColor, height, padding) => StyleSheet.create({
container: {
backgroundColor: buttonColor,
alignItems: "center",
justifyContent: "center",
width: "100%",
height: height,
padding: padding,
},
title: {
color: "black",
fontSize: 18,
},
btn: {
color: "black",
padding: "10%",
backgroundColor: "white",
borderRadius: "5px",
alignSelf: "center",
textAlign: "center",
margin: "5%",
},
});
export default DifficultScreen;
Upvotes: 8
Reputation: 559
style property only support a single object with style properties in it, so you need some way to merge a property inside an style object, actually we can do this using javascript spread operator or by passing the style properties as an array
change this :
<View style={styles.container}>
to
<View style={{...styles.container, backgroundColor: activeBtn}}/>
or to :
<View style={[styles.container, {backgroundColor: activeBtn}]}/>
Upvotes: 4
Reputation: 12222
What you can do is use it within the style of the container like so:
change this:
<View style={styles.container}>
to:
<View style={[styles.container, {backgroundColor: activeBtn}]}/>
This is the way to add dynamic styling to component
Upvotes: 1
Reputation: 815
import React, { useState } from "react"; import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
const DifficultScreen = (props) => {
const [activeBtn, setActiveBtn] = useState(styles.btnRed);
const confirmHandler = () => {
setActiveBtn(styles.btnGreen);
};
return (
<View>
<View style={styles.container}>
<Text style={styles.title}>Difficult screen is showing</Text>
</View>
<View>
<TouchableOpacity onPress={confirmHandler} style={activeBtn}>
<Text>Confirm</Text>
</TouchableOpacity>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: activeBtn,
alignItems: "center",
justifyContent: "center",
width: "100%",
height: 90,
padding: 35,
},
title: {
color: "black",
fontSize: 18,
},
btnRed: {
color: "black",
padding: "10%",
backgroundColor: "white",
borderRadius: "5px",
alignSelf: "center",
textAlign: "center",
margin: "5%",
},
btnGreen: {
color: "green",
padding: "10%",
backgroundColor: "white",
borderRadius: "5px",
alignSelf: "center",
textAlign: "center",
margin: "5%",
},
});
export default DifficultScreen;
Upvotes: -2