React Native Hooks - How use useStates in Styles - reactjs

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;

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;

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}]}/>

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;

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

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)
}
}

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;

Related

react native typescript get event target

i am new to react native with typescript and i have a problem
i want to get the text from the Text component so it mean when i press the Text i will console log it
i cant get the target value
i try also currentTarget
but it will give me a huge array of object with ton of keys without any target value
import { GestureResponderEvent, StyleSheet, Text, View } from "react-native";
import React, { useState } from "react";
import Card from "../../components/card/Card";
import ChooseLotteryNumber from "../../components/choose_lottery_number/ChooseLotteryNumber";
const CreateUser = () => {
const [selectedNumbers, setSelectedNumbers] = useState<number[]>([]);
const onSelectNumbers = (e: GestureResponderEvent )=>{
console.log(e.currentTarget)
};
return (
<View>
<Card>
<View>
<Text onPress={onSelectNumbers}>choose numbers!</Text>
</View>
<View style={styles.number_container}>
</View>
</Card>
</View>
);
};
export default CreateUser;
const styles = StyleSheet.create({
number_container: {
flexDirection: "row",
flexWrap: "wrap",
justifyContent: "center",
backgroundColor: "white",
borderRadius: 10,
},
number: {
fontSize: 24,
margin: 6,
borderWidth: 1,
borderRadius: 5,
textAlign: "center",
width: 35,
},
});

Error: "undefined is not an object (evaluating '_reactNative.Stylesheet.create') (Device"

I am new to react native and need help. I created two components one
is for TextInput and another for button, I imported the Button
component in textInput and it show error. can someone help me figure
out the error I made here. I am getting error undefined is not an
object(evalutaing;?_reactnative,stylesheet.create')*
and folder structure in the picture attached
this is button Component
import React from 'react';
import { TouchableOpacity, Text, Stylesheet } from 'react-native';
export const Button = ({
style = {},
textStyle = {},
size = 125,
...props
}) => {
return (
<TouchableOpacity style={\[styles(size).radius, style\]}>
<Text style={\[styles.text, textStyle\]}>{props.title}</Text>
</TouchableOpacity>
);
};
**error is likely to be here**
const styles = (size) => Stylesheet.create({
radius: {
borderRadius: size / 3,
width: size,
hieght: size,
alignItems: 'center',
borderColor: 'white',
},
text: {
color: '#fff',
fontSize: 20,
},
});
this is textInput component
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
import Constants from 'expo-constants';
import { TextInput } from 'react-native-paper';
import { Card } from 'react-native-paper';
import {Button} from '../components/Button';
// You can import from local files
// or any pure javascript modules available in npm
export const Something = () => {
return (
<View style={styles.container}>
<View style={styles.titleContainer}>
<Text style={styles.title}> input something here</Text>
<TextInput />
<Button title="+" />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
titleContainer: {
flex: 0.5,
padding: 20,
justifyContent: 'center',
},
title: {
fontWeight: 'bold',
color: 'white',
fontSize: 30,
},
});
Mispelled height maybe?
const styles = (size) => Stylesheet.create({
radius: {
borderRadius: size / 3,
width: size,
hieght: size, <-------------------- hieght
alignItems: 'center',
borderColor: 'white',
},
text: {
color: '#fff',
fontSize: 20,
},
});

How can we create Side Tabs in React Native

Creating Side Menu in React Application.
This would work both with Expo and react
Create a Navigation Service(Navigation-service.ts)
import { NavigationActions } from 'react-navigation';
function navigate(routeName: any, params?: any) {
NavigationActions.navigate({
routeName,
params
});
setRoute(routeName);
}
export default {
navigate
}
After this
create a new file sidemnu.tsx
import NavigationService from Navigation-service.ts;
import { View, TouchableHighlight, Image } from 'react-native';
openHome() {
NavigationService.navigate('Home');
}
render(){
return (
<View style={[this.props.isLoggedIn ? styles.container : styles.containerHidden]}>
<View style={[this.props.isLoggedIn ? styles.tabContainer : styles.tabContainerHidden]}>
<View>
<TouchableHighlight
style={this.props.currentTab === 'Home' ? styles.activeTab : styles.menuBtnContainer}
onPress={() => this.openHome()}
disabled={!this.props.isLoggedIn}
underlayColor='red'
>
<Image
source='any image url'
/>
</TouchableHighlight>
</View>
</View>
</View>
);
}
Add style
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
container: {
width: 108,
backgroundColor: '#002A5C',
borderTopColor: '#002457',
borderWidth: 1
},
containerHidden: {
width: 108,
backgroundColor: '#002A5C'
},
tabContainer: {
flex: 1,
flexDirection: 'column'
},
tabContainerHidden: {
flex: 1,
display: 'none'
},
activeTab: {
backgroundColor: '#008cc3',
height: 108,
width: 108,
padding: 10,
alignSelf: 'center',
justifyContent: 'center'
},
menuBtnContainer: {
height: 80,
width: 80,
alignSelf: 'center',
justifyContent: 'center'
},
});
Call in app.tsx file
<Sidemnu />
Whenever you want to display this side menu.
If you have any queries, please write back.

CLOSED White space between header and image background React-Native

I have a little problem in my react-native mobile app.
There is a Space between the header and the Background Image.
How can I remove it, like the Background Image is next to the Header ?
Image
App.js
import AppNavigator from './navigation/AppNavigator';
import Header from './components/Header';
export default function App(props) {
const [isLoadingComplete, setLoadingComplete] = useState(false);
if (!isLoadingComplete && !props.skipLoadingScreen) {
return (
<AppLoading
startAsync={loadResourcesAsync}
onError={handleLoadingError}
onFinish={() => handleFinishLoading(setLoadingComplete)}
/>
);
} else {
return (
<View style={styles.container}>
<Header title="Header" />
{Platform.OS === 'ios' && <StatusBar backgroundColor="#C2185B" barStyle="default" />}
<AppNavigator />
</View>
);
}
}
Header.js
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
const Header = props => {
return (
<View style={styles.header}>
<Text style={styles.headerTitle}>MyStadium</Text>
</View>
)
};
const styles = StyleSheet.create({
header: {
width: '100%',
height:90,
backgroundColor: 'black',
paddingTop: 36,
alignItems: 'center',
justifyContent:'center',
},
headerTitle: {
color:'white',
fontSize: 18
}
});
export default Header;
And The AppNavigator is the base file in the tabs pre-config react-native project.
Thanks for your help
remove paddingTop: 36 from container styles
like below
const styles = StyleSheet.create({
header: {
width: '100%',
height: 90,
backgroundColor: 'black',
alignItems: 'center',
justifyContent:'center',
},
headerTitle: {
color:'white',
fontSize: 18
}
});
Ok I got this !
Just have to remove my Header.js and use de navigationOptions like this
HomeScreen.navigationOptions = {
title: 'MyStadium',
headerStyle: {
backgroundColor: 'black'
},
headerTintColor: 'white',
headerTitleStyle: {
fontWeight: 'bold'
}
};

How to pass value as prop and insert into component as CSS style (React Native)?

I've got a reusable functional component called CardSection. I want to pass use different values of flex for different CardSection components.
Because of this, I want to pass the value of flex as a prop down into the CardSection component. E.g.:
<CardSection flex='1' />
<CardSection flex='3' />
However, if I try to add the key-value pair for flex into my style object, I get an error because I'm trying to set a key of flex with a value on an object that is meant to be immutable:
import React from 'react';
import { View } from 'react-native';
const CardSection = props => {
styles.container.flex = props.flex; // <---- Causes mutation error
return (
<View style={styles.container}>
{props.children}
</View>
);
};
const styles = {
container: {
borderBottomWidth: 1,
padding: 5,
backgroundColor: '#fff',
justifyContent: 'space-between',
borderColor: '#ddd',
position: 'relative',
borderWidth: 2,
borderColor: 'red',
}
};
export default CardSection;
What's the best way to insert custom flex values in this case?
you can do it following way
import React from "react";
import { View, StyleSheet } from "react-native";
class Main extends React.Component {
static getCardStyle(flexValue) {
return StyleSheet.create({
container: {
flex: flexValue,
borderBottomWidth: 1,
padding: 5,
backgroundColor: "#fff",
justifyContent: "space-between",
borderColor: "#ddd",
position: "relative",
borderWidth: 2,
borderColor: "red"
}
});
}
render() {
return <View style={getCardStyle(this.props.flex).container}>{props.children}</View>;
}
}
export default Main;
Another Best way:
import React from 'react';
import { View } from 'react-native';
const CardSection = props => {
return (
<View style={styles.container(props.flex)}>
{props.children}
</View>
);
};
const styles = {
container: (flexValue) => { return {
borderBottomWidth: 1,
padding: 5,
flex:flexValue
backgroundColor: '#fff',
justifyContent: 'space-between',
borderColor: '#ddd',
position: 'relative',
borderWidth: 2,
borderColor: 'red',
}}
};
export default CardSection;
you can create the stylesheet object property as function. then you called the styles property as a function.
class Main extends React.Component {
render() {
containerStyle = styles.container(this.props.flex)
return <View style={containerStyle}>{props.children}</View>;
}
}
const styles = StyleSheet.create({
container: (flexValue) => {
flex: flexValue,
borderBottomWidth: 1,
padding: 5,
backgroundColor: "#fff",
justifyContent: "space-between",
borderColor: "#ddd",
position: "relative",
borderWidth: 2,
borderColor: "red"
}
});
You should not mutate the object. Create a fresh object and assign:
const CardSection = props => {
const containerStyle = { ...style.container, props.flex }
return (
<View style={containerStyle}>
{props.children}
</View>
);
};
Use composition instead of mutation:
style={[styles.container, { flex: props.flex }]}
Also, use a number for flex: <CardSection flex={1} />.
You can just destructure your flexValue from props and then pass set it to the flex property. You also have to move that styleSheet inside your component for it to have access to flexValue. You code will look like this:
import React from "react";
import { View } from "react-native";
const CardSection = ({ flexValue }) => {
const styles = {
container: {
flex: flexValue,
borderBottomWidth: 1,
padding: 5,
backgroundColor: "#fff",
justifyContent: "space-between",
borderColor: "#ddd",
position: "relative",
borderWidth: 2,
borderColor: "red",
},
};
return <View style={styles.container}>{props.children}</View>;
};
export default CardSection;

Resources