How to check for current active page in component? - react-native

I would like to apply different styling to a component, for example i have a back icon here
import React from 'react';
import { StyleSheet } from 'react-native';
import { Icon } from '#ui-kitten/components';
export const BackIcon = () => (
<Icon
style={styles.icon}
fill='#FFFFFF'
name='arrow-back-outline'
/>
);
const styles = StyleSheet.create({
icon: {
width: 35,
height: 35,
bottom: 115,
right: 145
},
});
Currently I only have 1 style applied to it, but I would like to know you can detect the current active page so that when the user is in page A the icon will be styled differently as to when the component is called in page B for instance.

You can pass it as a prop from the parent component
<Parent>
<BackIcon current/>
<BackIcon />
<BackIcon />
</Parent>
import React from 'react';
import { StyleSheet } from 'react-native';
import { Icon } from '#ui-kitten/components';
export const BackIcon = (props) => (
<Icon
style={props.current ? styles.activeIcon : styles.icon}
fill='#FFFFFF'
name='arrow-back-outline'
/>
);
const styles = StyleSheet.create({
icon: {
width: 35,
height: 35,
bottom: 115,
right: 145
},
activeIcon:
{
color:'orange',
width: 35,
height: 35,
bottom: 115,
right: 145
}
});

Related

React Native Snap Carousel Functional Component Issue

I'm using this snack as a template for implementing my own carousel component. This template is using Class Component and I converted it to a Functional component
https://snack.expo.io/#bd-arc/react-native-snap-carousel-%7C-example-with-custom-interpolations
I added this to my project and I believe some error is happening when rendering the Carousel but I'm unable to tell. It renders - but not all the components are rendering. I have only changed the Carousel itself to a function component. The problem is the is not showing below the Carousel - also if I add multiple VideoCarousel's, only the first one displays.
My code is below
App.js
import React from 'react';
import { View } from 'react-native';
import Header from './components/header';
import VideoCarousel from './components/videoCarousel';
import tailwind from 'tailwind-rn';
const App = () => {
return (
<View style={tailwind('flex pt-12 items-center bg-gray-300 h-full')}>
<Header />
<VideoCarousel />
<VideoCarousel />
</View>
)
};
export default App;
VideoCarousel.js
import React, { useState } from 'react';
import { Text, View, Dimensions, StyleSheet, Alert } from 'react-native';
import Carousel from 'react-native-snap-carousel'; // Version can be specified in package.json
import { scrollInterpolator, animatedStyles } from './../utils/animations';
const SLIDER_WIDTH = Dimensions.get('window').width;
const ITEM_WIDTH = Math.round(SLIDER_WIDTH * 0.7);
const ITEM_HEIGHT = Math.round(ITEM_WIDTH * 3 / 4);
const DATA = [];
for (let i = 0; i < 10; i++) {
DATA.push(i)
}
const VideoCarousel = () => {
const [index, setIndex] = useState(0);
_renderItem = (index) => {
return (
<View style={styles.itemContainer}>
<Text style={styles.itemLabel}>{`Item ${index.index}`}</Text>
</View>
);
}
return (
<View>
<Carousel
data={DATA}
renderItem={this._renderItem}
sliderWidth={SLIDER_WIDTH}
itemWidth={ITEM_WIDTH}
containerCustomStyle={styles.carouselContainer}
inactiveSlideShift={0}
onSnapToItem={(index) => setIndex(index)}
scrollInterpolator={scrollInterpolator}
slideInterpolatedStyle={animatedStyles}
useScrollView={true}
/>
<Text style={styles.counter}>
Test
</Text>
</View>
);
}
const styles = StyleSheet.create({
carouselContainer: {
marginTop: 50
},
itemContainer: {
width: ITEM_WIDTH,
height: ITEM_HEIGHT,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'dodgerblue'
},
itemLabel: {
color: 'white',
fontSize: 24
},
counter: {
marginTop: 400,
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
backgroundColor: "black",
}
});
export default VideoCarousel;

MultipleScreens(like a stack) on top of one another in react native

In react native, can we achieve a UI where there are multiple screens stacked on top of each other with each screen stacking on top of the other on click of a button.
Let's say, there is Screen A. Upon click of a button, Screen B is placed as a stack on Screen A and screen A is still partly visible as Screen B doesn't occupy the entire screen layout. Similarly, Screen C adds up to the stack upon the click of a button in Screen B and screen B is still visible along with screen A in the background. All these come with a side animation from the left (similar to navigation drawer). With a common button, all the above screens can be popped out from the stack and the previous screen comes to the top with a side animation again, this time to the right.
I wanted to understand if the above is possible in react native? If yes, how I can achieve it? I wish I can show the design but I cannot do that atm.
With react-native-vertical-view-pager you can do it.
install with:
npm install --save react-native-vertical-view-pager
or with yarn (if you use yarn):
yarn add react-native-vertical-view-pager
and use as follow:
import React from 'react';
import { StyleSheet, Text, View, Dimensions } from 'react-native';
import VerticalViewPager from 'react-native-vertical-view-pager';
const { width, height } = Dimensions.get('window');
export default class App extends React.Component {
render() {
return (
<VerticalViewPager
showsVerticalScrollIndicator={false}>
<View style={[styles.page_container, {backgroundColor: 'pink'}]}>
<Text>Page1: Open up App.js to start working on your app!</Text>
</View>
<View style={[styles.page_container, {backgroundColor: 'olive'}]}>
<Text>Page2: Changes you make will automatically reload.</Text>
</View>
<View style={[styles.page_container, {backgroundColor: 'lightblue'}]}>
<Text>Page3: Shake your phone to open the developer menu.</Text>
</View>
</VerticalViewPager>
);
}
}
const styles = StyleSheet.create({
page_container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
width,
height
}
});
with your screens on the place of the views.
I could achieve this functionality using a very cool library named 'react-native-modalfy'.
import React, { PureComponent } from 'react'
import {
Easing,
Dimensions,
StatusBar,
StyleSheet,
Text,
View,
} from 'react-native'
import { ModalProvider, createModalStack } from 'react-native-modalfy'
import CardModal from './modals/CardModal'
import Button from './components/Button'
const { width } = Dimensions.get('screen')
const config = { ModalA: CardModal, ModalB: CardModal, ModalC: CardModal }
const defaultOptions = {
transitionOptions: animatedValue => ({
opacity: animatedValue.interpolate({
inputRange: [0, 1, 2],
outputRange: [0, 1, .9],
}),
transform: [
{
perspective: 2000
},
{
translateX: animatedValue.interpolate({
inputRange: [0, 1, 2],
outputRange: [-width / 2, 0, 25],
}),
},
{
scale: animatedValue.interpolate({
inputRange: [0, 1, 2],
outputRange: [1.2, 1, .9],
}),
},
],
}),
animateInConfig: {
easing: Easing.bezier(.42,-0.03,.27,.95),
duration: 450,
},
animateOutConfig: {
easing: Easing.bezier(.42,-0.03,.27,.95),
duration: 450,
},
}
const stack = createModalStack(config, defaultOptions)
class App extends PureComponent {
render() {
return (
<ModalProvider stack={stack}>
<View style={styles.container}>
<StatusBar animated hidden translucent />
<Text style={styles.title}>RNM</Text>
<Button label="Open ModalA" modalToOpen="ModalA" color="tomato" />
<Button label="Open ModalB" modalToOpen="ModalB" color="darkcyan" />
<Button label="Open ModalC" modalToOpen="ModalC" color="deeppink" />
</View>
</ModalProvider>
)
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'indigo',
alignItems: 'center',
justifyContent: 'center'
},
title: {
color: 'white',
fontSize: 54,
fontWeight: 'bold',
marginBottom: 50,
},
})
export default App
import React, { PureComponent } from 'react'
import {
Button as ButtonModule,
Dimensions,
StyleSheet,
Text,
View,
} from 'react-native'
import Button from '../components/Button'
const { width: ww, height: wh } = Dimensions.get('screen')
class CardModal extends PureComponent {
componentDidMount() {
const { modal } = this.props
this.modalListenerID = modal.addListener('onAnimate', this._handleAnimation)
}
componentWillUnmount() {
this.modalListenerID?.remove()
}
_handleAnimation = animatedValue => {
const { currentModal } = this.props.modal
console.info(`${currentModal}:`, animatedValue)
}
render() {
const {
currentModal,
closeModal,
closeModals,
closeAllModals,
params: { color },
} = this.props.modal
return (
<View style={[styles.card]}>
<Text style={styles.title(color)}>{currentModal}</Text>
<Button label="Open ModalA" modalToOpen="ModalA" color="tomato" />
<Button label="Open ModalB" modalToOpen="ModalB" color="darkcyan" />
<Button label="Open ModalC" modalToOpen="ModalC" color="deeppink" />
<ButtonModule title="Close" onPress={closeModal} color="dodgerblue" />
<ButtonModule title={`Close all ${currentModal}`} onPress={() => closeModals(currentModal)} color="dodgerblue" />
<ButtonModule title="Close all modals" onPress={closeAllModals} color="red" />
</View>
)
}
}
const styles = StyleSheet.create({
title: color => ({
color,
fontSize: 48,
fontWeight: 'bold',
marginBottom: 50,
}),
card: {
marginRight : 90,
width: ww,
height: wh,
backgroundColor: 'cyan',
elevation: 0,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 0,
},
})
export default CardModal
import React, { PureComponent } from 'react'
import { TouchableOpacity, StyleSheet, Text } from 'react-native'
import { withModal } from 'react-native-modalfy'
class Button extends PureComponent {
openModal = () => {
const { color, modalToOpen, modal } = this.props
modal.openModal(modalToOpen, { color })
}
render() {
const { color, label } = this.props
return (
<TouchableOpacity onPress={this.openModal} style={styles.button(color)}>
<Text style={styles.label}>{label}</Text>
</TouchableOpacity>
)
}
}
const styles = StyleSheet.create({
button: backgroundColor => ({
backgroundColor,
paddingHorizontal: 60,
paddingVertical: 21,
borderRadius: 21,
marginBottom: 30,
}),
label: {
fontSize: 16,
fontWeight: '800',
color: 'white',
textAlign: 'center',
},
})
export default withModal(Button)

StackNavigation props not working as expected

I've configured the navigation as best I can, however there are no errors when the app runs. The buttons change shade to show they've been pressed but sadly they don't navigate.
I've tried different versions of Expo, React and StackNavigation too.
Here's a copy of the MainNavigator:
import ArtGallery from "./ArtGallery";
import HighNet from "./HighNet";
import Economist from "./Economist";
import Main from "./Main";
import { createStackNavigator, createAppContainer } from "react-navigation";
const screens = {
ArtGallery: {
screen: ArtGallery
},
HighNet: {
screen: HighNet
},
Economist: {
screen: Economist
},
Main: {
screen: Main
}
}
const config = {
headerMode: 'none',
initialRouteName: 'Economist'
}
const MainNavigator = createStackNavigator(screens, config);
export default createAppContainer(MainNavigator);
And here's a copy of the Main.js:
import React, { Component } from "react";
import { Center } from "#builderx/utils";
import Button2 from "../symbols/button2";
import Button21 from "../symbols/button21";
import Button22 from "../symbols/button22";
import { View, StyleSheet, Text } from "react-native";
import { MainNavigation } from "../screens/MainNavigator";
export default class Main extends Component {
render() {
return (
<View style={styles.root}>
<Center horizontal>
<Text style={styles.title}>TV Network</Text>
</Center>
<Center horizontal>
<Button2
onPress={() => this.props.navigation.navigate("Winkball")}
style={styles.winkTv}
buttonContent="WinkBall TV" />
</Center>
<Center horizontal>
<Button21
onPress={() => this.props.navigation.navigate("HighNet")}
style={styles.highNet}
buttonContent="High Net Worth Channel"
/>
</Center>
<Center horizontal>
<Button22
onPress={() => this.props.navigation.navigate("Economist")}
style={styles.artGalleryTv}
buttonContent="Economist TV"
/>
</Center>
</View>
);
}
}
const styles = StyleSheet.create({
root: {
backgroundColor: "white",
flex: 1
},
title: {
height: "6.19%",
width: "64.53%",
top: 68,
position: "absolute",
backgroundColor: "transparent",
fontSize: 48,
color: "rgba(109,104,104,1)"
},
winkTv: {
top: 309,
position: "absolute",
height: "5.665024630541872%",
width: "33.06666666666666%"
},
highNet: {
top: 384,
position: "absolute",
height: "5.665024630541872%",
width: "57.333333333333336%"
},
artGalleryTv: {
top: 460,
position: "absolute",
width: "42.13%",
height: "4.06%"
}
});

How to set default props values to custom state less component in React Native

I have a really simple component, called Divider here is the source code:
import React from "react";
import { StyleSheet, View } from "react-native";
export default class Divider extends React.Component {
render() {
return (
<View style = { styles.separator } />
);
}
}
const styles = StyleSheet.create({
separator: {
height: StyleSheet.hairlineWidth,
marginBottom: 8,
backgroundColor: "#FFFFFF80",
},
});
What I am trying to achieve is that the values in styles.separator becomes the default values of this component, since those are the values which I am using in most cases, but in some edge cases I need to change the marginBottom to 16 for example.
So most case I just want to do <Divider />, but sometimes <Divider marginBottom = 16 />
What I have currently is something like this below, but obviously this doesn't work.
import React from "react";
import { StyleSheet, View } from "react-native";
export default class Divider extends React.Component {
static defaultPropts = {
marginTop: 0,
marginBottom: 8,
backgroundColor: "#FFFFFF80",
}
render() {
return (
<View style = {{
height: StyleSheet.hairlineWidth,
marginTop: {this.props.marginTop},
marginBottom: {this.props.marginBottom},
backgroundColor: {this.props.backgroundColor},
}} />
);
}
}
You can receive your custom style by props and use them in your component style as array. When you call the props style after the component's, it will overwrite any equal style property it already has.
For example, let's say you have a component named 'Card', you can write your component like this:
<View style={[style.cardStyle, props.style]}>
{props.children}
</View>
And call it like this <Card style={{ backgroundColor: '#FFFFFF'}} />
So it's getting all defined 'cardStyle' from it's own component, also adding the styles received by props.
Hope it helps.
EDIT:
You can try something like this
import React from "react";
import { StyleSheet, View } from "react-native";
const Divider = (props) => {
<View style = {{
height: StyleSheet.hairlineWidth,
marginTop: {this.props.marginTop},
marginBottom: {this.props.marginBottom},
backgroundColor: {this.props.backgroundColor},
}} />
}
Divider.defaultProps = {
marginTop: 0,
marginBottom: 8,
backgroundColor: "#FFFFFF80",
}
export default Divider;
Let me know if it works for you.
you can do like this
export default class Divider extends React.Component {
render() {
return (
<View style = {{
height: StyleSheet.hairlineWidth,
marginTop: {this.props.marginTop},
marginBottom: {this.props.marginBottom},
backgroundColor: {this.props.backgroundColor},
}} />
);
}
}
Divider.defaultProps = {
marginTop: 0,
marginBottom: 8,
backgroundColor: "#FFFFFF80",
}
So after researching a bit I found out that this works.
import React from "react";
import { Dimensions, StyleSheet, View } from "react-native";
export default class Divider extends React.Component {
static defaultProps = {
customWidth: Dimensions.get("window").width / 2.0,
}
render() {
const halfWidth = this.props.customWidth
return (
<View style = { [styles.separator, {width: halfWidth}] } />
);
}
}
const styles = StyleSheet.create({
separator: {
height: StyleSheet.hairlineWidth,
backgroundColor: "#FFFFFF80",
},
});
So now whenever I use <Divider /> its width gonna be half of the screen size, but if I dod <Divider customWidth = { 10 }, then it will overwrite the default value and will be 10 dp instead.

react navigation giving error undefined is not an object(evaluating 'this.props.navigation')

I am new to react native I am using expo app to run my code I dont have index file as explained in other questions all the files i have are app.js ,login.js, router.js,home.js and My application flow should go like this Login> on button click > Home
but on button click I am getting error Undefined is not an object(evaluating 'this.props.navigation'),
please help me where i am going wrong.
thanks in advance.
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Login from './containers/Login/Login';
import {Navigate} from './containers/Navigation/Router';
import { AppRegistry } from 'react-native';
export default class App extends React.Component {
render() {
return (<Login navigation={this.props.navigation}/>);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
import React from 'react';
import { StyleSheet, Text,TextInput,Button,Image, View } from 'react-native';
import Navigate from '../Navigation/Router';
import RNChart from 'react-native-chart';
export default class Login extends React.Component{
static navigationOptions = {
title:'Login',
};
render() {
const navigate = this.props.navigation;
return (
<View style={styles.container}>
<RNChart style={styles.chart}
chartData={chartData}
verticalGridStep={5}
type="bar"
xLabels={xLabels}>
</RNChart>
<Image
source={require('../../NCS.png')}
/>
<TextInput
style={styles.textInput}
placeholder="Username"
/>
<TextInput
style={styles.textInput}
placeholder="Password"
secureTextEntry= {true}
/>
<Button
onPress={this._handlePress}
title="Login"
color="#0086b3"
/>
</View>
);
}
_handlePress(event) {
//navigate('Home')
this.props.navigation.navigate('Home', {name: 'Home'})
}
}
var chartData = [
{
name:'BarChart',
type:'bar',
color:'purple',
widthPercent:0.6,
data:[
30, 1, 1, 2, 3, 5, 21, 13, 21, 34, 55, 30
]
},
{
name:'LineChart',
color:'gray',
lineWidth:2,
showDataPoint:false,
data:[
10, 12, 14, 25, 31, 52, 41, 31, 52, 66, 22, 11
]
}
];
var xLabels = ['0','1','2','3','4','5','6','7','8','9','10','11'];
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
textInput: {
padding: 10,
width: 200,
},
chart: {
position: 'absolute', top: 16, left: 4, bottom: 4,right: 16
}
});
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {Navigate} from '../Navigation/Router';
export default class Home extends React.Component {
static navigationOptions = {
title:'Home',
};
render() {
return (
<View style={styles.container}>
<Text> Work under progress</Text>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import {StackNavigator} from 'react-navigation';
import Login from '../Login/Login';
import Home from '../Home/Home';
export default Navigate = StackNavigator({
Home: { screen: Home, },
});
The problem is that React Navigation is not connected to your App component as #Eden mentioned. The component you return in App needs to be your StackNavigator.
Here's a very good tutorial that show's this with a TabNavigator.
https://hackernoon.com/getting-started-with-react-navigation-the-navigation-solution-for-react-native-ea3f4bd786a4