Passing props into external stylesheet in React Native? - javascript

I'm new to React and React Native. At the moment for each component I'm breaking the code into 2 separate files:
index.js for all the React code, and;
styles.js for the StyleSheet
Is there a way to pass props into the external StyleSheet?
Example:
index.js:
render() {
const iconColor = this.props.color || '#000';
const iconSize = this.props.size || 25;
return (
<Icon style={styles.icon} />
);
}
Example styles.js:
const styles = StyleSheet.create({
icon : {
color: iconColor,
fontSize: iconSize
}
});
The code above does not work, but it's more there just to get the point across of what I'm trying to do. Any help is much appreciated!

I rather to have my styles in a separate file styles.js.
Inside styles.js:
export const styles = (props) => StyleSheet.create({
icon : {
color: props.iconColor,
fontSize: props.iconSize
}
}
Inside your main class you can pass the value
return (
<Icon style={styles(this.props).icon} />
);
Alternatively you can those value directly
so it would be
export const styles = (iconColor,iconSize) => StyleSheet.create({
icon : {
color: iconColor,
fontSize: iconSize
}
}
and inside your main class
return (
<Icon style={styles(this.props,iconColor,
this.props.iconSize).icon} />
);

i'm sending noFooter boolean prop in a style sheet
<View style={styles.mainFooterCont(noFooter)}>
<Text> Testing </Text>
</View>
and receiving it like
mainFooterCont: noFooter => ({
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-end',
paddingBottom: noFooter ? 0 : 20,
paddingTop: Metrics.ratio(noFooter ? 0 : 5),
}),

Create a class that takes iconColor and iconSize as arguments and returns a StyleSheet object
// styles.js
export default class StyleSheetFactory {
static getSheet(iconSize, iconColor) {
return StyleSheet.create({
icon : {
color: iconColor,
fontSize: iconSize
}
})
}
}
// index.js
render() {
let myStyleSheet = StyleSheetFactory.getSheet(64, 'red')
}

Just wrap stylesheet in a function where you can optionally pass props.
Instead of:
const styles = StyleSheet.create({
Title: { color: 'white' }
});
You do:
const styles = (props?: any) => StyleSheet.create({
Title: { color: 'white' }
});
And now when you add them to your components, instead of
style={styles.Title}
You do:
style={styles(propsObjectHere).Title}
and since this is optional and you have no props to pass, just do:
style={styles().Title}
P.S. ignore the type if you, for some reason, are not using TypeScript :P

If you do not prefer to create a class then simply just create a function followed by a key and return an object from the function, you just have to pass the parameter by which you want to evaluate the condition. here is the exmple
export const Style = StyleSheet.create({
locatorTextInputContainer: locatorType => ({
flexDirection: 'row',
backgroundColor: locatorType == 'None' || locatorType == '' ? GColors.separatorColor : GColors.white,
marginBottom: 10,
paddingBottom: 5,
marginStart: 10,
marginEnd: 10,
})
})
and you can use it as follows
<View style={Style.locatorTextInputContainer(locatorType)}>
<TextInput
value={sourceLocator}
onChangeText={(text) => {
dispatch(setSourceLocator(text))
}}/>
</View>

Solution:
render() {
const iconColor = this.props.color || '#000';
const iconSize = this.props.size || 25;
return (
<Icon style={{...styles.icon, color: iconColor, fontSize: iconSize }} />
Example styles.js:
const styles = StyleSheet.create({
icon : {
color: iconColor,
fontSize: iconSize
}})

Here is a simpler solution.
Component
<View
style={{
...styles?.tabItem_bottomView,
backgroundColor: selected ? Color?.blue : Color?.white,
}}
/>
You can just use the stylesheet as before. Nothing to edit there.

Related

React Native: Unexpected text node: . A text node cannot be a child of a <View>

I am working on making a React Native app and I am getting the error:
Unexpected text node: . A text node cannot be a child of a <View>.
I cannot figure out what text node this error refers to. My goal is to render an array of views.
Here is a minimal code snippet reproducing the error:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
function fun() {
const views = [];
const style = {backgroundColor: 'red', height: 100, width: 100};
for (let i=0; i<3; i++) {
views.push(
<View key={i} style={style}/>
)
}
return views;
}
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<View> {fun()} </View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
The problem is that a function that is supposed to be a JSX component, or in this case return a JSX component, must be single JSX element and not an array of JSX elements.
Hence, you need to add a top level component which could be just a fragment.
function fun() {
const views = []
const style = { backgroundColor: "red", height: 100, width: 100 }
for (let index = 0; index < 3; index++) {
views.push(<View key={index} style={style} />)
}
return <>{views}</>
}
You are returning an array of views. You must return views as the children. Try something like:
function fun() {
const style = { backgroundColor: "red", height: 100, width: 100 };
return [0, 1, 2].map(() => <View key={i} style={style} />);
}
export default function App() {
return (
<View style={styles.container}>
<Text>Open up App.js to start working on your app!</Text>
<View> {fun()} </View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});

Function inside Text Tag React Native

I am having an issue with the react-native Text tag. I could not figure out why this happening. Please, help out.
I need to use the function retrieveData inside the Text tag but that gives an error. What am I doing wrong? Thanks
I have set the data(mobileNumber as key) using AsyncStorage inside another file.
import React, { Component } from "react";
import {
View,
Text,
TextInput,
SafeAreaView,
TouchableOpacity,
AsyncStorage
} from "react-native";
export default class PhoneCode extends Component {
constructor(props) {
super(props);
this.state = {
};
}
onVerify = () => {};
onPress = () => {
alert("Sending...");
};
tappedVerify = () => {
console.log("clicked")
};
render() {
const { code, isCodeValid } = this.state;
const _retrieveData = async () => {
try {
const value = await AsyncStorage.getItem("mobileNumber");
if (value !== null) {
// We have data!!
return value;
}
} catch (error) {
// Error retrieving data
console.log("failed");
}
};
return (
<SafeAreaView style={styles.container}>
<View style={styles.contentArea}>
<Text style={{}}> Enter... </Text>
<View style={styles.codeArea}>
<Text style={styles.codeInput}> {_retrieveData()} </Text> // this is the problem
<TextInput
placeholder="Enter here"
underlineColorAndroid="transparent"
style={styles.textInput}
maxLength={6}
autoGrow={true}
maxHeight={40}
keyboardType={"phone-pad"}
onChangeText={(text) =>
this.setState({
//....
})
}
/>
</View>
</View>
</SafeAreaView>
Here is the style object
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "flex-start",
alignItems: "center"
},
contentArea: {
justifyContent: "flex-start",
alignItems: "center",
width: '100%',
height: '100%',
paddingTop: 80,
paddingLeft: 20,
paddingRight: 20
},
textInput: {
textAlign: 'center',
height: 50,
width: '18%',
borderWidth: 2,
borderColor: 'gray',
borderRadius: 20,
backgroundColor: "#FFFFFF"
}
})
Here is the error message
ExceptionsManager.js:74 Invariant Violation: Objects are not valid as a React child (found: object with keys {_40, _65, _55, _72}). If you meant to render a collection of children, use an array instead.
Doing this solves my problem. It might help someone else.
<Text style={styles.codeInput}> {`${_retrieveData()}`} </Text>

React Native Text color not working

I've got a Text component inside a TouchableOpacity which I want to change the color depend on a var.
Here is my code:
import React, { Component } from "react";
import { StyleSheet, Text, View, TouchableOpacity } from "react-native";
var flag = false;
export default class MyTest extends Component {
changeColor() {
flag = true;
}
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={{ flex: 1, backgroundColor: "#888888", margin: 20 }}
onPress={this.changeColor.bind(this)}
>
<Text style={[{ color: "blue" }, flag ? { color: "red" } : false]}>
One
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
backgroundColor: "#F5FCFF"
}
});
I have tried to use this.state.textColor but no result. I've also tried to use that in styles variable but again, not working.
Any idea?
The flag variable is not in your component state, so the component will not re-render when it changes.
Put it in your component state instead and toggle it with setState and it will work.
class MyTest extends Component {
state = { flag: true };
changeColor = () => {
this.setState(previousState => {
return { flag: !previousState.flag };
});
};
render() {
return (
<View style={styles.container}>
<TouchableOpacity
style={{ flex: 1, backgroundColor: "#888888", margin: 20 }}
onPress={this.changeColor}
>
<Text style={{ color: this.state.flag ? "red" : "blue" }}>One</Text>
</TouchableOpacity>
</View>
);
}
}
You have to give style to the Text for color.
<Text style={styles.steelblue}>Sign Up</Text>
Give this style to Text.
const styles = StyleSheet.create({
steelblue: {
color: "steelblue",
},
});
try this example this may help you to solve problem.
import React, { Component } from 'react';
import { Platform, StyleSheet, View, Text } from 'react-native';
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Text style={[styles.setFontSize,styles.setColorRed]}> React Native Font example 1</Text>
<Text style={[styles.setFontSize,styles.setColorPink]}> React Native Font example 2</Text>
<Text style={[styles.setFontSize,styles.setColorPurple]}> React Native Font example 3</Text>
<Text style={[styles.setFontSize,styles.setColorBlue]}> React Native Font example 4</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center'
},
setFontSize: {
fontSize: 20,
fontWeight : 'bold'
},
setColorRed : {
color: '#f44336'
},
setColorPink :{
color: '#e91e63'
},
setColorPurple :{
color: '#9c27b0'
},
setColorBlue :{
color: '#2196f3'
},
});

Can't call openDrawer() in DrawerLayoutAndroid, react-native

I'm a newbie in react-native. What I try to do is putting a drawer on the screen and open it with the "menu" button in the toolbar.
I know that I must use callback functions, I previously searched a lot of topics and related questions such as this one but I couldn't do it. Getting Almost crazy. Here's my code:
/**
* #flow
*/
const React = require('react');
const ReactNative = require('react-native');
const { View, Text, DrawerLayoutAndroid } = ReactNative;
class Profile extends React.Component<{}> {
static navigationOptions = {
title: 'Profile',
headerRight: <Text>Menu</Text>,
};
constructor() {
super();
this.openDrawer = this.openDrawer.bind(this);
}
openDrawer() {
this.ref.drawer.openDrawer();
}
render() {
const navigationView = (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<Text style={{ margin: 10, fontSize: 15, textAlign: 'left' }}>Im in the Drawer!</Text>
</View>
);
return (
<DrawerLayoutAndroid
drawerWidth={300}
drawerPosition={DrawerLayoutAndroid.positions.Left}
renderNavigationView={() => navigationView}
ref={(_drawer) => {
this.drawer = _drawer;
}}
>
<View style={{ flex: 1, alignItems: 'center' }}>
<Text style={{ margin: 10, fontSize: 15, textAlign: 'right' }}>Hello</Text>
<Text
style={{ margin: 10, fontSize: 15, textAlign: 'right' }}
onPress={this.openDrawer()}
>
World!
</Text>
</View>
</DrawerLayoutAndroid>
);
}
}
export default Profile;
Every time I run the code, I get the "undefined is not an object".
Also, I don't know how to put openDrawer() inside the static navigationOptions.
Help is really appreciated!

Can't find variable: StyleSheet

I'm studying React Native with this site https://www.tutorialspoint.com/react_native/react_native_animations.htm
However, there is a problem while i'm trying to open app on iPhone. According to error it cannot find variable, though it's imported.
import React, { Component } from 'react';
import { View, LayoutAnimation, TouchableOpacity, Text, StyleSheet} from 'react-native';
export default class Animations extends Component {
state = {
myStyle: {
height: 100,
backgroundColor: 'red'
}
};
expandElement = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
this.setState({
myStyle: {
height: 400,
backgroundColor: 'red'
}
})
};
collapseElement = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
this.setState({
myStyle: {
height: 100,
backgroundColor: 'red'
}
})
};
render() {
return (
<View>
<View>
<View style={this.state.myStyle}/>
</View>
<TouchableOpacity>
<Text style={styles.button} onPress = {this.expandElement}>
Expand
</Text>
</TouchableOpacity>
<TouchableOpacity>
<Text style={styles.button} onPress = {this.collapseElement}>
Collapse
</Text>
</TouchableOpacity>
</View>
)
}
}
const styles = StyleSheet.create({
button: {
borderWidth: 1,
borderColor: 'red',
color: 'red',
textAlign: 'center',
marginTop: 50,
padding: 10
}
});
Ah... I've found the problem. It was in other component which had styles but no elements to them and had no imported StylesSheet since I corrected it to new conditions but forgot about block with styles.

Categories

Resources