I have a shared style with error:
export const modalStyle(height)= { // <-- Whats the syntax for adding parameter here?
width:MODAL_WIDTH,
height:height,
backgroundColor:color_theme_light.mainGreen,
borderRadius:22,
justifyContent:"center",
alignItems:"center",
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.20,
shadowRadius: 1.41,
elevation: 2
}
How can I add a parameter to it, so when I call this style I can change the height dynamically?
import {modalStyle} from './modalStyles'
<View style={modalStyle(40)}>
...
</View>
In your case, you are having two common ways to declare and export the modalStyle function.
Function declaration:
export function modalStyle(height) ({})
Arrow function:
export const modalStyle = (height) => ({})
Related
Alright Im just trying to loop the background color of a view, fading between 3-4 colors. I found How to animate the backgroundColor of a ScrollView in React Native and have copied verbatim, but looking at the Snack, I believe this answer is out of date.
With the following, I get the error:
this.setState is not a function
export default props => {
let [fontsLoaded] = useFonts({
'Inter-SemiBoldItalic': 'https://rsms.me/inter/font-files/Inter-SemiBoldItalic.otf?v=3.12',
'SequelSans-RomanDisp' : require('./assets/fonts/SequelSans-RomanDisp.ttf'),
'SequelSans-BoldDisp' : require('./assets/fonts/SequelSans-BoldDisp.ttf'),
'SequelSans-BlackDisp' : require('./assets/fonts/SequelSans-BlackDisp.ttf'),
});
if (!fontsLoaded) {
return <AppLoading />;
} else {
//Set states
this.state = {
backgroundColor: new Animated.Value(0)
};
this.setState({ backgroundColor: new Animated.Value(0) }, () => {
Animated.timing(this.state.backgroundColor, {
toValue: 100,
duration: 5000
}).start();
});
var color = this.state.colorValue.interpolate({
inputRange: [0, 300],
outputRange: ['rgba(255, 0, 0, 1)', 'rgba(0, 255, 0, 1)']
});
const styles = StyleSheet.create({
container: { flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: this.state.backgroundColor.interpolate({
inputRange: [0, 100],
outputRange: ["#00aaFF", "#808080"]
})
},
Then I reference this style here:
return (
<Animated.View style={styles.container}>
<View style={styles.textWrapper}>
<Text style={styles.myText}>Login</Text>
</View>
</Animated.View>
);
What am I doing wrong here?
UPDATE: - Rendered more hooks than during the previous render
export default props => {
let [fontsLoaded] = useFonts({
'Inter-SemiBoldItalic': 'https://rsms.me/inter/font-files/Inter-SemiBoldItalic.otf?v=3.12',
'SequelSans-RomanDisp' : require('./assets/fonts/SequelSans-RomanDisp.ttf'),
'SequelSans-BoldDisp' : require('./assets/fonts/SequelSans-BoldDisp.ttf'),
'SequelSans-BlackDisp' : require('./assets/fonts/SequelSans-BlackDisp.ttf'),
});
if (!fontsLoaded) {
return <AppLoading />;
} else {
//Set states
const [backgroundColor, setBackgroundColor] = useState(new Animated.Value(0));
useEffect(() => {
setBackgroundColor(new Animated.Value(0));
}, []); // this will be only called on initial mounting of component,
// so you can change this as your requirement maybe move this in a function which will be called,
// you can't directly call setState/useState in render otherwise it will go in a infinite loop.
useEffect(() => {
Animated.timing(this.state.backgroundColor, {
toValue: 100,
duration: 5000
}).start();
}, [backgroundColor]);
var color = this.state.colorValue.interpolate({
inputRange: [0, 300],
outputRange: ['rgba(255, 0, 0, 1)', 'rgba(0, 255, 0, 1)']
});
const styles = StyleSheet.create({
container: { flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: color
},
textWrapper: {
height: hp('70%'), // 70% of height device screen
width: wp('80%'), // 80% of width device screen
backgroundColor: '#fff',
justifyContent: 'center',
alignItems: 'center',
},
myText: {
fontSize: hp('2%'), // End result looks like the provided UI mockup
fontFamily: 'SequelSans-BoldDisp'
}
});
return (
<Animated.View style={styles.container}>
<View style={styles.textWrapper}>
<Text style={styles.myText}>Login</Text>
</View>
</Animated.View>
);
}
};
You can not use this inside a functional component. The only mistake you made is you are trying to set state using this.setState inside a functional component instead of using useState hook which does the same work for functional component.
Just change your setState functionality using useState and useEffect hook as below:-
//Set states
const [backgroundColor, setBackgroundColor] = useState(new Animated.Value(0));
const [colorValue, setColorValue] = useState(new Animated.Value(0));
useEffect(() => {
setBackgroundColor(new Animated.Value(0));
}, []); // this will be only called on initial mounting of component,
// so you can change this as your requirement maybe move this in a function which will be called,
// you can't directly call setState/useState in render otherwise it will go in a infinite loop.
useEffect(() => {
Animated.timing(backgroundColor, {
toValue: 100,
duration: 5000
}).start();
}, [backgroundColor]);
var color = colorValue.interpolate({
inputRange: [0, 300],
outputRange: ['rgba(255, 0, 0, 1)', 'rgba(0, 255, 0, 1)']
});
This is how it could be done in a class component using useState and useEffect hooks, Enjoy!
Ok guys, I've been trying to figure this out for the past 3 days and I can't find a solution, please keep in mind that I am self-taught and I've been studying react native for like 3 months now.
Anyways, I have a custom button with a defined style and everytime that I render my button it loads with the style presented in its file:
Botaozudo.js:
import React from 'react';
import { Text, TouchableOpacity, StyleSheet } from 'react-native';
export default class Botaozudo extends React.Component {
render() {
const { titulo, evento } = this.props;
return (
<TouchableOpacity
style={styles.button}
onPress={() => evento()}>
<Text style={styles.txtButton}>{titulo}</Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
btnAlinhar: {
alignItems: 'flex-end',
marginRight: 20,
paddingTop: 7
},
button: {
backgroundColor: '#a082c9',
width: 100,
height: 40,
borderRadius: 10
},
button2: {
backgroundColor: '#a082c9',
width: 300,
height: 90,
borderRadius: 10
},
txtButton: {
color: '#fff',
fontSize: 20,
textAlign: 'center',
paddingVertical: 5
}
});
Lets say that I want two different buttons on my App.js, one that looks like exactly as above and another one with different size and background color. In my mind I just have to do something like this (for the different one):
<Botaozudo
style={styles.newBtn}
titulo='I am a button'
event={() =>
console.log('yup I am a button')}/>
const styles = StyleSheet.create({
newBtn: {
backgroundColor: '#7c7070',
width: 200,
height: 100
}
});
But the thing is that my Botaozudo doesn't know what that style={} prop means. And what I can't figure out is HOW to make my custom component understand it.
Thanks in advance,
Install https://www.npmjs.com/package/prop-types
Then in Botaozudo.js:
import React from 'react';
import { Text, TouchableOpacity, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
export default class Botaozudo extends React.Component {
static propTypes = {
// Custom style for Botaozudo. Requires object
componentStyle: PropTypes.object,
};
static defaultProps = {
componentStyle: styles,
};
render() {
const { titulo, event, componentStyle } = this.props;
return (
<TouchableOpacity style={componentStyle.newBtn} onPress={() => event()}>
<Text style={styles.txtButton}>{titulo}</Text>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
btnAlinhar: {
alignItems: 'flex-end',
marginRight: 20,
paddingTop: 7,
},
button: {
backgroundColor: '#a082c9',
width: 100,
height: 40,
borderRadius: 10,
},
button2: {
backgroundColor: '#a082c9',
width: 300,
height: 90,
borderRadius: 10,
},
txtButton: {
color: '#fff',
fontSize: 20,
textAlign: 'center',
paddingVertical: 5,
},
});
and in App.js:
<Botaozudo
componentStyle={styles}
titulo='I am a button'
event={() =>
console.log('yup I am a button')}/>
const styles = StyleSheet.create({
newBtn: {
backgroundColor: '#7c7070',
width: 200,
height: 100
}
});
I'm having problems rendering an icon I'm supplying through a prop in a custom component. Here is my custom component:
import React from 'react';
import { View, Image, StyleSheet, Text } from 'react-native';
export class MoreIcon extends React.Component {
render() {
return(
<View style={styles.topViewStyle}>
<View style={styles.circleStyle}>
<Image source={this.props.iconSource} style={styles.iconStyle} />
</View>
<Text style={styles.moreIconText}>{this.props.iconText}</Text>
</View>
);
}
}
const styles = StyleSheet.create({
topViewStyle: {
alignItems: 'center',
justifyContent: 'center',
},
moreIconText: {
fontSize: 12,
fontWeight: 'bold',
color: '#fff',
lineHeight: 1.17,
height: 14,
},
iconStyle: {
width: 30,
height: 30,
},
circleStyle: {
width: 58,
height: 58,
borderRadius: 50,
borderColor: 'rgba(255, 255, 255, 0.3)',
borderWidth: 2,
}
});
The problem is, when I supply a source attribute in the component like this:
<MoreIcon iconText='Home' iconSource={require('../../assets/icons/dashboard.svg')} />
Nothing shows up in the circle, and it looks like this:
What am I doing wrong to where the prop I'm supplying doesn't show up in the MoreIcon tab? (the path is correct fyi)
You'll need to convert your SVGs to be compatible with the react-native-svg library. Luckily, there are a few great examples on the Usage section of the readme.
There's also a great example on Snack
After you've converted them, you'll be able to import them as normal constants.
EDIT:
As per Adam's comment below, using the react-native-svg-uri library now seems like the simpler approach to the SVG problem.
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.
I'm trying to get a React Native app set up following this post and then ported over to ES6. Here's the main page code:
"use strict";
import React, { Component } from 'react';
import Camera from 'react-native-camera';
import {
AppRegistry,
StyleSheet,
Text,
View,
TextInput,
TouchableHighlight,
} from 'react-native';
export default class AwesomeProject extends Component {
constructor(props) {
super(props);
this.state = {cameraType: Camera.constants.Type.back};
}
render() {
return (
<Camera
ref="cam"
style={styles.container}
type={this.state.cameraType}>
<View style={styles.buttonBar}>
<TouchableHighlight style={styles.button} onPress={this._switchCamera.bind(this)}>
<Text style={styles.buttonText}>Flip</Text>
</TouchableHighlight>
<TouchableHighlight style={styles.button} onPress={this._takePicture.bind(this)}>
<Text style={styles.buttonText}>Take</Text>
</TouchableHighlight>
</View>
</Camera>
);
}
_switchCamera: () => {
var state = this.state;
console.log(this.state);
state.cameraType = state.cameraType === Camera.constants.Type.back ? Camera.constants.Type.front : Camera.constants.Type.back;
this.setState(state);
}
_takePicture: () => {
console.log(this.refs);
this.refs.cam.capture(function(err, data) {
console.log(err, data);
});
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center",
backgroundColor: "transparent",
},
buttonBar: {
flexDirection: "row",
position: "absolute",
bottom: 25,
right: 0,
left: 0,
justifyContent: "center"
},
button: {
padding: 10,
color: "#FFFFFF",
borderWidth: 1,
borderColor: "#FFFFFF",
margin: 5
},
buttonText: {
color: "#FFFFFF"
}
});
AppRegistry.registerComponent('AwesomeProject', () => AwesomeProject);
I am getting a weird error saying both state.cameraType is undefined and this.refs is undefined. I have a hunch that something is not getting bound and my this is not pointing to right thing but I have tried using both arrow functions and explicitly binding. See comment below. Anyway, I am not sure why it's acting up, any ideas?
Very similar to this post except I have tried both the proposed solutions so I feel like something else is missing or I'm doing the binding wrong.
edit: Is there reason to be downvoted? Am I not being clear on something :o
It turns out manual binding is the way to go, just needed to reload the app. I did not have hot-swapping enabled. Alternatively, arrow functions should also work.
Another thing to point out, for iOS 10 and above, you'll have to set 2 things in the Info.plist file, Privacy - Camera Usage Description and Privacy - Photo Library Usage. It can be any string value.