How to navigate from carousel slide? - react-native

I just started to learn React Native and don't understand how to make possible navigation from carousel slides. I have a carousel with 4 slides in it and I want to make it possible for a user to go to specific pages after pressing on each of these slides. For every slide, there is a different page.
I tried const navigation = useNavigation(); method, but it did not work, because a slide is not a function.
I have routes in my App.js:
export default function App () {
return (
<NavigationContainer>
<Stack.Navigator initialRouteName="Home"
screenOptions={{contentStyle:{backgroundColor:'#FFFFFF'}, headerTitle: (props) => <LogoTitle {...props} />, headerRight: (props) => <RightTitle {...props} /> }}>
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="ItemsCategories" component={ItemsCategories} />
<Stack.Screen name="Feature1" component={Feature1} />
<Stack.Screen name="Feature2" component={Feature2} />
</Stack.Navigator>
</NavigationContainer>
);
}
Here is my code of the Carousel so far:
import React, {Component} from 'react';
import { Text, View, SafeAreaView, Image, ImageBackground, StyleSheet, Pressable, navigation } from 'react-native';
import Carousel from 'react-native-snap-carousel';
import { useNavigation } from '#react-navigation/native';
import { NavigationContainer } from '#react-navigation/native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
const horizontalMargin = 20;
const slideWidth = 280;
const slideHeight=470
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
flex: 1,
justifyContent: "center"
},
text: {
color: "white",
fontSize: 42,
lineHeight: 84,
fontWeight: "bold",
textAlign: "center",
textShadowColor: 'rgba(0, 0, 0, 0.75)',
textShadowOffset: {width: -1, height: 1},
textShadowRadius: 10,
width: 350
},
safe: {
position: 'absolute',
left: 0,
top: 0,
height: 360 ,
paddingTop: 10,
paddingBottom: 1
}
});
export default class HomeCarousel extends Component {
constructor(props){
super(props);
this.state = {
activeIndex:0,
carouselItems: [
{
navigate: "Feature1",
image: require('./assets/feature1.png'),
title:"Feature1",
},
{
navigate: "Feature2",
image: require('./assets/feature2.png'),
title:"Feature2",
},
{
navigate: "Feature3",
image: require('./assets/feature3.png'),
title:"Feature3",
},
{
navigate: "Feature 4",
image: require('./assets/feature4.png'),
title:"Feature 4",
},
]
}
}
_renderItem({item,index}){
return (
<Pressable onPress={()=>navigation.navigate(item.navigate)}>
<View style={{
backgroundColor:'floralwhite',
borderRadius: 5,
height: 360,
padding: 0,
marginLeft: 0,
marginRight: 0, }}>
<ImageBackground source={item.image} resizeMode="cover" style={styles.image}>
<Text style={styles.text}>{item.title}</Text>
</ImageBackground>
</View>
</Pressable>
)
}
render() {
return (
<SafeAreaView style={styles.safe}>
<View style={{ flex: 1, flexDirection:'row', justifyContent: "center" }}>
<Carousel
layout={"default"}
ref={ref => this.carousel = ref}
data={this.state.carouselItems}
sliderWidth={400}
itemWidth={400}
renderItem={this._renderItem}
onSnapToItem = { index => this.setState({activeIndex:index}) } />
</View>
</SafeAreaView>
);
}
}

If you just make HomeCarousel a functional component then you can do this below and it will work.
export default function HomeCarousel() {
const [activeIndex,setActiveIndex] = React.useState(0); // search useState online
const [carouselItems,setCarouselItems] = React.useState( [
{
navigate: "Feature1",
image: require('./assets/feature1.png'),
title:"Feature1",
},
{
navigate: "Feature2",
image: require('./assets/feature2.png'),
title:"Feature2",
},
{
navigate: "Feature3",
image: require('./assets/feature3.png'),
title:"Feature3",
},
{
navigate: "Feature 4",
image: require('./assets/feature4.png'),
title:"Feature 4",
},
]);
const ref = React.useRef(null); // search useRef online
const Item =({item,index})=> {
const navigation = useNavigation(); // Now you can use it
return (
<Pressable onPress={()=>navigation.navigate(item.navigate)}>
<View style={{
backgroundColor:'floralwhite',
borderRadius: 5,
height: 360,
padding: 0,
marginLeft: 0,
marginRight: 0, }}>
<ImageBackground source={item.image} resizeMode="cover" style={styles.image}>
<Text style={styles.text}>{item.title}</Text>
</ImageBackground>
</View>
</Pressable>
)
}
return (
<SafeAreaView style={styles.safe}>
<View style={{ flex: 1, flexDirection:'row', justifyContent: "center" }}>
<Carousel
layout={"default"}
ref={ref}
data={carouselItems}
sliderWidth={400}
itemWidth={400}
renderItem={Item}
onSnapToItem = { index =>setActiveIndex(index) } />
</View>
</SafeAreaView>
);
}

Related

How to add DarkMode to Navigator in App.js

I have to add DarkMode switch to one of the Screen which applies to all the screen in React Native IOS App.
Below is the App.js where I wrap my main navigator inside ThemeProvider
import React from 'react';
import {Provider} from 'react-redux';
import {createStore, combineReducers,applyMiddleware} from 'redux';
import ReduxThunk from 'redux-thunk';
import authReducer from './store/reducers/auth';
import deviceReducer from './store/reducers/device';
import FR_Navigator from './navigation/FR_Navigator';
import downloadReducer from './store/reducers/download';
import { RootSiblingParent } from 'react-native-root-siblings';
import { ThemeProvider} from './theme/theme-context';
const rootReducer = combineReducers({
auth: authReducer,
download:downloadReducer,
device:deviceReducer
});
const store = createStore(rootReducer,applyMiddleware(ReduxThunk));
export default class App extends React.Component {
render() {
return (
<Provider store={store}>
<ThemeProvider>
<FR_Navigator />
</ThemeProvider>
</Provider>
);
}
}
Below is the FRNavigator which has Settings Page which sets DarkMode.
FRNavigator.js
import React from 'react';
import { View,StyleSheet,SafeAreaView,Button,ScrollView,Text} from 'react-native';
import { createSwitchNavigator,createAppContainer } from 'react-navigation';
import {createStackNavigator,StackViewTransitionConfigs} from 'react-navigation-
stack';
import MainPage from '../screens/FaceRecog/MainPage';
import UploadPage from '../screens/FaceRecog/UploadPage';
import { createDrawerNavigator,DrawerItems} from 'react-navigation-drawer';
import Icon from 'react-native-vector-icons/Ionicons';
import DownloadPage from '../screens/FaceRecog/DownloadPage';
import RateUsScreen from '../screens/FaceRecog/RateUsScreen';
import ForgotPasswordScreen from '../screens/UI/ForgotPasswordScreen';
import ImageBrowserScreen from '../screens/FaceRecog/ImageBrowserScreen';
import LoginScreen from '../screens/UI/LoginScreen';
import RegisterScreen from '../screens/UI/Register';
import AddDevicePage from '../screens/FaceRecog/AddDevicePage';
import LogoutComponent from '../components/FaceRecog/LogoutComponent'
import DrawerHeader from '../components/FaceRecog/DrawerHeader';
import CommunicateComponent from '../components/FaceRecog/CommunicateComponent';
import ManageDevice from '../screens/FaceRecog/ManageDevicePage';
import Register from '../screens/UI/Register';
import Settings from '../screens/FaceRecog/Settings';
const AuthNavigator = createStackNavigator(
{
Login:
{
screen:LoginScreen,
navigationOptions: {
headerShown: false,
}
},
SignUp:
{
screen:Register
},
ForgotPasswordPage:
{
screen:ForgotPasswordScreen,
navigationOptions: {
headerShown: true,
}
}
},
);
const MainPageNavigator = createStackNavigator({
Home:MainPage,
AddDevice:AddDevicePage,
Upload:UploadPage,
ImagePicker:ImageBrowserScreen,
ManageDev:ManageDevice,
Setting:
{
screen:Settings,
transitionConfig: () => StackViewTransitionConfigs.SlideFromRightIOS,
},
RateUs:RateUsScreen,
})
const DrawerNavigator = createDrawerNavigator(
{
Home:
{
screen:MainPageNavigator,
navigationOptions:{
drawerIcon:(
<Icon
name='md-home-sharp' size={25} color='grey'/>
)
}
},
Download:
{
screen:DownloadPage,
navigationOptions:{
drawerIcon:(
<Icon
name='md-download'
type='ionicons' size={25} color='grey'onPress={ () => {
}}/>
)
}
},
Exit:
{
screen:Register,
navigationOptions:{
drawerIcon:(
<Icon
name='exit-outline'
type='ionicons' size={25} color='grey' onPress={ () => {
}}/>
)
}
}
},
{
contentOptions:{
activeTintColor: '#e91e63',
},
contentComponent: (props) =>
<ScrollView>
<SafeAreaView style={{flex:1}} forceInset={{ top: 'always', horizontal: 'never',
height:180 }}>
<View style={{width:'100%', backgroundColor: 'white', }}>
<DrawerHeader />
</View>
<DrawerItems {...props} />
<LogoutComponent />
<View
style={{
borderBottomColor: 'grey',
borderBottomWidth: 1
}}/>
<View style={styles.communicateview}>
<Text style={styles.communicatetext}>Communicate</Text>
<CommunicateComponent {...props}/>
</View>
</SafeAreaView>
</ScrollView>,
},
);
const MainNavigator = createSwitchNavigator({
Auth: AuthNavigator,
App:DrawerNavigator
});
const styles = StyleSheet.create({
communicatetext:{
fontWeight:'800',
color:'grey'
},
communicateview:{
top:'3%',
left:'3%'
}
})
export default createAppContainer(MainNavigator);
Below is the Settings Page where I have added Toggle button to set DarkMode:
Settings.js
import React,{useState,useContext} from 'react';
import { View, StyleSheet ,Text,Switch,StatusBar,TouchableOpacity,Button} from
'react-native';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import HeaderButton from '../../components/UI/HeaderButton';
import Icon from 'react-native-vector-icons/Entypo';
import { ThemeContext } from '../../theme/theme-context';
const Settings = props => {
const { dark, theme, toggle } = useContext(ThemeContext);
return <View style={styles.container}>
<View style={styles.appsettingstextview}>
<Text style={styles.appsettingstext}>App Settings </Text>
<View style={styles.box}>
<View style={{right:80}}>
<Icon name='adjust' type='entypo' size={40} color='#00008B'/>
</View>
<View style={{right:70}}><Text style={{fontWeight:'bold'}}>Dark Mode</Text></View>
<View style={{left:80}}>
<Switch
trackColor={{ false: "#767577", true: "#ccc" }}
thumbColor={dark ? "#fff" : "#f4f3f4"}
onChange={toggle} value = {dark} />
</View>
</View>
</View>
</View>
};
const styles = StyleSheet.create({
container:{
flex:1,paddingTop:40,paddingLeft:20,
paddingBottom: 60
},
apppermissiontextview:{
},
appsettingstext:{
fontSize:17,
color:'#0437F2',
fontWeight:'bold'
},
apppermissiontextview:{
top:'5%',
},
apppermissiontext:{
fontSize:17,
color:'#0437F2',
fontWeight:'bold'
},
box: {
shadowColor: 'rgba(0,0,0, .4)', // IOS
shadowOffset: { height: 1, width: 1 },
shadowOpacity: 1, // IOS
shadowRadius: 1, //IOS
backgroundColor: '#fff',
elevation: 2, // Android
height: 80,
width:380,
borderRadius: 5,
marginVertical: 40,
backgroundColor: "#FFFFFF",
alignItems: "center",
justifyContent: "center",
flexDirection: 'row',
},
text: {
fontSize: 14,
fontWeight: "bold",
margin: 8,
color: "#000",
textAlign: "center"
}
});
Settings.navigationOptions = navData =>{
return{
headerTitle: 'Settings',
headerTitleStyle:{
color:'white',
},
headerTitleAlign:"left",
headerStyle: {
backgroundColor: '#0437F2',
},
headerLeft: () =>
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
//title="Menu"
iconName={'chevron-back-outline'}
onPress={() => {
//navData.navigation.toggleDrawer();
navData.navigation.navigate('Home');
}}
/>
</HeaderButtons>
}
};
export default Settings;
If I run the above program, when I toggle the Switch, nothing happens.Can anyone say how to add the Settings.js Page to work with FRNavigator to support darkmode toggle switch.Thanks in Advance.
I added darkmode style as style={[styles.box,{ backgroundColor: theme.backgroundColor }]}> to the View in the Settings Page and I could get switch between dark and light theme.Below is the Settings code changes I made :
Settings.js:
import React,{useState,useContext} from 'react';
import { View, StyleSheet
,Text,Switch,StatusBar,TouchableOpacity,Button} from 'react-native';
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
import HeaderButton from '../../components/UI/HeaderButton';
import Icon from 'react-native-vector-icons/Entypo';
import { ThemeContext } from '../../theme/theme-context';
const Settings = () => {
const { dark, theme, toggle } = useContext(ThemeContext);
return <View style={styles.container}>
<View style={styles.appsettingstextview}>
<Text style={styles.appsettingstext}>App Settings </Text>
<View style={[styles.box,{ backgroundColor: theme.backgroundColor }]}>
<View style={{right:80}}><Icon
name='adjust'
type='entypo' size={40} color='#00008B'/>
</View>
<View style={{right:70}}><Text style={[styles.darkmodetext,
{color:theme.color}]}>Dark Mode</Text></View>
<View style = {styles.containerSwitch}>
<Switch
trackColor={{ false: "#ccc", true: "#d43790" }}
thumbColor={dark ? "#f5dd4b" : "#f4f3f4"}
ios_backgroundColor="#3e3e3e"
onChange={toggle} value = {dark} />
</View>
</View>
</View>
</View>
};
const styles = StyleSheet.create({
container:{
flex:1,paddingTop:40,paddingLeft:20,
paddingBottom: 60
},
appsettingstext:{
fontSize:17,
color:'#0437F2',
fontWeight:'bold'
},
darkmodetext:{
fontWeight:'bold',
fontSize:18
},
box: {
shadowColor: 'rgba(0,0,0, .4)', // IOS
shadowOffset: { height: 1, width: 1 },
shadowOpacity: 1, // IOS
shadowRadius: 1, //IOS
backgroundColor: '#fff',
elevation: 2, // Android
height: 80,
width:380,
borderRadius: 5,
marginVertical: 40,
backgroundColor: "#FFFFFF",
alignItems: "center",
justifyContent: "center",
flexDirection: 'row',
bottom:'7%'
},
text: {
fontSize: 14,
fontWeight: "bold",
margin: 8,
color: "#000",
textAlign: "center"
},
containerSwitch:{
marginBottom:50,
top:'6%',
left:'110%'
}
});
Settings.navigationOptions = navData =>{
return{
headerTitle: 'Settings',
headerTitleStyle:{
color:'white',
},
headerTitleAlign:"left",
headerStyle: {
backgroundColor: '#0437F2',
},
headerLeft: () =>
<HeaderButtons HeaderButtonComponent={HeaderButton}>
<Item
//title="Menu"
iconName={'chevron-back-outline'}
onPress={() => {
//navData.navigation.toggleDrawer();
navData.navigation.navigate('Home');
}}
/>
</HeaderButtons>
}
};
export default Settings;

undefined is not an object (evaluating '_this.props.navigation') Expo React Native

I am getting undefined is not an object evaluating _this.props.navigation. Here is my code. I want to use Flatlist to call the screen 'PlaceorderScreen.js' number of times from the component 'NearbyLSP.js' present in the 'HomeScreen.js'. Also I had referred many solutions for the above problem but yet I didn't get how to get through it. I am a beginner in react-native, So I had used expo for app development.
HomeScreen.js
import React from "react";
import {
View,
Text,
StyleSheet,
SafeAreaView,
TextInput,
Platform,
StatusBar,
ScrollView,
TouchableOpacity,
Dimensions,
Animated,
} from "react-native";
import Icon from 'react-native-vector-icons/Ionicons'
import Category from './Category'
import Expressmode from './Expressmode'
import { FlatList } from "react-native-gesture-handler";
import NearbyLSP from "./NearbyLSP";
const { width } = Dimensions.get('window')
const data = [
{id:'1',name:'LSP1',phone:'1234',email:'abc#gmail.com'},
{id:'2',name:'LSP2',phone:'0234',email:'abc2#gmail.com'},
{id:'3',name:'LSP3',phone:'2234',email:'abc3#gmail.com'}
]
const renderList = ((item) =>{
return <TouchableOpacity
onPress={()=> this.props.navigation.navigate('PlaceOrder')}
activeOpacity={0.7}>
<NearbyLSP name={item.name}/>
</TouchableOpacity>
})
export default class HomeScreen extends React.Component {
componentDidMount() {
this.scrollY = new Animated.Value(0)
this.startHeaderHeight = 80
this.endHeaderHeight = 50
if (Platform.OS == 'android') {
this.startHeaderHeight = 100 + StatusBar.currentHeight
this.endHeaderHeight = 70 + StatusBar.currentHeight
}
this.animatedHeaderHeight = this.scrollY.interpolate({
inputRange: [0, 50],
outputRange: [this.startHeaderHeight, this.endHeaderHeight],
extrapolate: 'clamp'
})
this.animatedOpacity = this.animatedHeaderHeight.interpolate({
inputRange: [this.endHeaderHeight, this.startHeaderHeight],
outputRange: [0, 1],
extrapolate: 'clamp'
})
this.animatedTagTop = this.animatedHeaderHeight.interpolate({
inputRange: [this.endHeaderHeight, this.startHeaderHeight],
outputRange: [-30, 10],
extrapolate: 'clamp'
})
this.animatedMarginTop = this.animatedHeaderHeight.interpolate({
inputRange: [this.endHeaderHeight, this.startHeaderHeight],
outputRange: [50, 30],
extrapolate: 'clamp'
})
}
render() {
return (
<SafeAreaView style={{ flex: 1 }}>
<View style={{ flex: 1 }}>
<Animated.View style={{ height: this.animatedHeaderHeight, backgroundColor: 'white', borderBottomWidth: 1, borderBottomColor: '#dddddd' }}>
<View style={{
flexDirection: 'row', padding: 10,
backgroundColor: 'white', marginHorizontal: 10,
shadowOffset: { width: 0, height: 0 },
shadowColor: 'black',
shadowOpacity: 0.2,
elevation: 1,
marginTop: null
}}>
<Icon name="ios-search" size={25} style={{ marginRight: 10 ,marginTop:5 , opacity:0.6}} />
<TextInput
underlineColorAndroid="transparent"
placeholder="Find LSP"
placeholderTextColor="grey"
style={{ flex: 1, fontWeight: '700', backgroundColor: 'white' }}
/>
</View>
</Animated.View>
<ScrollView
scrollEventThrottle={16}
onScroll={Animated.event(
[
{ nativeEvent: { contentOffset: { y: this.scrollY } } }
]
)}
>
<View style={{ flex: 1, backgroundColor: 'white', paddingTop: 20 }}>
<Text style={styles.text}>
Laundry Service Provider Type
</Text>
<View style={{ height: 130, marginTop: 20 }}>
<ScrollView
horizontal={true}
showsHorizontalScrollIndicator={false}
>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('PlaceOrder')} activeOpacity={0.7}><Category name="Dry Clean" /></TouchableOpacity>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('PlaceOrder')} activeOpacity={0.7}><Category name="Iron"/></TouchableOpacity>
<TouchableOpacity onPress={()=> this.props.navigation.navigate('PlaceOrder')} activeOpacity={0.7}><Category name="Dry Clean + Iron" /></TouchableOpacity>
</ScrollView>
</View>
<View style={{ marginTop: 40}}>
<Text style={styles.text}>
Find Nearby LSP
</Text>
<Text style={{ fontWeight: '100', marginTop: 10,paddingHorizontal: 20 }}>
Verified LSP Providers
</Text>
<View style={{ marginTop: 20, paddingHorizontal: 15
}}>
<FlatList
data={data}
renderItem={({item})=>{
return renderList(item)
}}
keyExtractor={item=>item.id}
navigation={this.props.navigation}
/>
</View>
</View>
</View>
<View style={{ marginTop: 40 }}>
<Text style={styles.text}>
Express Mode
</Text>
<View style={{ paddingHorizontal: 20, marginTop: 20, flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between' }}>
<Expressmode width={width}
name="LSP1"
type="Dry Clean"
price={82}
rating={4}
/>
<Expressmode width={width}
name="LSP2"
type="Iron + Dry Clean"
price={82}
rating={4}
/>
<Expressmode width={width}
name="LSP3"
type="Iron"
price={82}
rating={4}
/>
</View>
</View>
</ScrollView>
</View>
</SafeAreaView>
);
;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: "center",
alignItems: "center"
},
text: {
fontSize: 24,
fontWeight:'700',
paddingHorizontal: 20
}
});
'HomeScreen.js' contains another component where I had successfully used the navigation to navigate to 'PlaceorderScreen.js'. But when I call this navigation inside Flatlist it gives the error.
NearbyLSP.js
import React from "react";
import { View, Text, StyleSheet, TouchableOpacity, Dimensions, Image } from "react-native";
import { Card } from "react-native-paper" ;
const { width } = Dimensions.get('window')
export default class NearbyLSP extends React.Component {
render() {
return (
<View>
<Card style={styles.mycard}>
<View style={{ width: width - 40, height: 200}} >
<Image
style={{ flex: 1, height: null, width: null, resizeMode: 'cover', borderRadius: 5, borderWidth: 1, borderColor: '#dddddd' }}
source={require('../assets/a.jpeg')}
/>
<Text>{this.props.name}</Text>
</View>
</Card>
</View>
);
}
}
const styles = StyleSheet.create({
mycard: {
margin: 5
}
});
App.js
import React from "react";
import { createAppContainer, createSwitchNavigator , createBottomTabNavigator } from "react-navigation";
import { createStackNavigator } from "react-navigation-stack";
import LoadingScreen from "./screens/LoadingScreen";
import LoginScreen from "./screens/LoginScreen";
import SignupScreen from "./screens/SignupScreen";
import HomeScreen from "./screens/HomeScreen";
import AboutScreen from "./screens/AboutScreen";
import PastorderScreen from "./screens/PastorderScreen";
import TrackScreen from "./screens/TrackScreen";
import ProfileScreen from "./screens/ProfileScreen";
import PlaceorderScreen from "./screens/PlaceorderScreen";
import MapsScreen from "./screens/MapsScreen";
import NearbyLSP from "./screens/NearbyLSP";
import { Ionicons , MaterialIcons } from '#expo/vector-icons';
import * as firebase from "firebase";
const firebaseConfig = {
apiKey: "AIzaSyAhwjD3jodBg6JGJ7Oo72r7-m2T5wwPaUg",
authDomain: "a4project-2d896.firebaseapp.com",
databaseURL: "https://a4project-2d896.firebaseio.com",
projectId: "a4project-2d896",
storageBucket: "a4project-2d896.appspot.com",
messagingSenderId: "181932238433",
appId: "1:181932238433:web:aa3f6fa3947976a8352c20",
measurementId: "G-SW6N6N8JYK"
};
firebase.initializeApp(firebaseConfig);
const HomeStack = createStackNavigator({
Home: HomeScreen,
NearbyLSP:NearbyLSP,
PlaceOrder:PlaceorderScreen
},
{
defaultNavigationOptions: {
title:'Home',
headerStyle: {
backgroundColor:'#12B2C2',
},
headerTintColor:'#fff',
headerTitleStyle:{
fontWeight:'bold'
}
}
})
const OrderStack = createStackNavigator({
Order: TrackScreen,
Maps: MapsScreen,
},
{
defaultNavigationOptions: {
title:'Orders',
headerStyle: {
backgroundColor:'#12B2C2',
},
headerTintColor:'#fff',
headerTitleStyle:{
fontWeight:'bold'
}
}
})
const PastorderStack = createStackNavigator({
Pastorder: PastorderScreen,
},
{
defaultNavigationOptions: {
title:'Pastorder',
headerStyle: {
backgroundColor:'#12B2C2',
},
headerTintColor:'#fff',
headerTitleStyle:{
fontWeight:'bold'
}
}
})
const ProfileStack = createStackNavigator({
Profile: ProfileScreen,
About: AboutScreen
},
{
defaultNavigationOptions: {
title:'Profile',
headerStyle: {
backgroundColor:'#12B2C2',
},
headerTintColor:'#fff',
headerTitleStyle:{
fontWeight:'bold'
}
}
})
const AuthStack = createStackNavigator({
Login: LoginScreen,
Signup: SignupScreen
},
{
defaultNavigationOptions: {
headerStyle: {
backgroundColor:'#12B2C2',
},
headerTintColor:'#fff',
headerTitleStyle:{
fontWeight:'bold'
}
}
})
const myTabs= createBottomTabNavigator({
Home:HomeStack,
Orders:OrderStack,
Profile:ProfileStack,
Pastorder:PastorderStack
},
{
defaultNavigationOptions: ({ navigation })=> {
return {
tabBarIcon:({tintColor})=>{
const { routeName } = navigation.state;
let myicon
if(routeName=="Home"){
myicon='md-home'
return <Ionicons name={myicon} size={30} color={tintColor}/>
}else if(routeName=="Profile"){
myicon='md-person'
return <Ionicons name={myicon} size={30} color={tintColor}/>
}else if(routeName=="Orders"){
myicon='md-book'
return <Ionicons name={myicon} size={30} color={tintColor}/>
}else if(routeName=="Pastorder"){
myicon='library-books'
return <MaterialIcons name={myicon} size={30} color={tintColor}/>
}
}
};
}
});
export default createAppContainer(
createSwitchNavigator(
{
Loading: LoadingScreen,
Auth: AuthStack,
App: myTabs
},
{
initialRouteName: "Loading"
},
)
);
Just writing navigation={this.props.navigation} in Flatlist won't let you navigate to the desired screen. You have to create a Touchable component in the Flatlist and add the navigation logic into the onPress logic of this Touchable Component.
this.props.navigation is a collection of data and methods, if you need to navigate through screens you need to use this.props.navigation.navigate('PlaceOrder')} instead, this is the method that does the navigation for you. You can console.log(this.props.navigation) to understand better.
Refer to how navigation is implemented in this answer https://stackoverflow.com/a/45407626/8851276
The code within FlatList of 'HomeScreen.js' is modified as follows
<FlatList
data={data}
renderItem={this.rendeList}
keyExtractor={item=>item.id}
/>
and the renderList function which was outside the class component is transferred inside and modified as
renderList = ({ item }) => {
return (
<TouchableOpacity
onPress={()=> this.props.navigation.navigate('PlaceOrder')}
activeOpacity={0.7}>
<NearbyLSP name={item.name}/>
</TouchableOpacity>
);
};
Due to transferring the renderList function inside the class component, it gets access to the this.props and it can be used for navigation to new screen.

React Navigation 4.x version issue when navigating to other screen

When Using react-navigation version 4.1.1
When navigating from one screen to another screen it is fluctuating and i am using ImageBackground there ,so first white blank screen appears after that imagebackground is loading which is very slow and i can easily see the transition over there .
I dont know what's the exact issue is there.
And for this new version i have to install libraries also for react navigation i.e.react-native screens,animated and maskedView ,safeareacontext.
So please any one know about this please let me know ..
Thanks in advance .
Here is a video for my app where i am getting image loading issue...
https://drive.google.com/open?id=16bdmxOC342uCQl3UL_hB8K0wznpbedge
Here is my APP.js File where i have created stack navigator..
import React, { Component } from 'react';
import { createAppContainer } from "react-navigation"
import { createStackNavigator } from 'react-navigation-stack';
import WelcomeScreen from './Screens/WelcomeScreen';
import Walkthorugh from './Screens/Walkthrough';
import Login from './Screens/Login';
import Signup from './Screens/Signup';
import Profile from './Screens/Profile';
import Wishlist from './Screens/Wishlish';
import Home from './Screens/Home';
import Cart from './Screens/Cart';
const notificationsel = require('./Screens/icons/notificationsel.png');
import { createBottomTabNavigator } from 'react-navigation-tabs';
import { enableScreens } from 'react-native-screens';
import { useScreens } from 'react-native-screens';
import {
StyleSheet,
Easing,
View, Animated, FlatList,
Text, Image, Alert, YellowBox, Button, ImageBackground,
TouchableWithoutFeedback, TouchableOpacity
} from 'react-native';
const welcomeStack = createStackNavigator({
Welcome:{screen:WelcomeScreen
},
});
const homeStack = createStackNavigator({
Home:{screen:Home
},
});
const profileStack = createStackNavigator({
Profile:{screen:Profile,
navigationOptions:{header:null}},
});
const cartStack = createStackNavigator({
Cart:{screen:Cart,
navigationOptions:{header:null}},
});
const wishlistStack = createStackNavigator({
Wishlist:{screen:Wishlist,
navigationOptions:{header:null}},
});
const HomeTabNavigator = createBottomTabNavigator({
Home : homeStack,
Profile : profileStack,
Cart : cartStack,
Wishlist : wishlistStack,
},
{
defaultNavigationOptions: ({ navigation }) => ({
tabBarOnPress: ({ navigation, defaultHandler }) => {
console.log('onPress:', navigation.state.routeName);
// if(navigation.state.routeName=='CallNow'){
// Linking.openURL(`tel:${'9414036555'}`)
// console.log("CallNow")
// }
defaultHandler()
},
tabBarIcon: ({ focused, horizontal, tintColor }) => {
const { routeName } = navigation.state;
let iconName;
if (routeName === 'Home') {
iconName = focused ? notificationsel : notificationsel;
}
else if (routeName === 'Profile') {
iconName = focused ? notificationsel : notificationsel;
}
else if (routeName === 'Cart') {
iconName = focused ? notificationsel : notificationsel;
}
else if (routeName === 'Wishlist') {
iconName = focused ? notificationsel : notificationsel;
}
// You can return any component that you like here!
return <Image source={iconName} style={{width:22,height:22}}/>
;
},
}),
tabBarOptions:{
activeTintColor: 'blue',
inactiveTintColor: '#000',
showLabel:true,
style:{backgroundColor:'#fff',padding:5}
},
}
);
const AppNavigator = createStackNavigator(
{
Home: {
screen: HomeTabNavigator,
// navigationOptions:{header:null}
},
Walkthorugh:{
screen:Walkthorugh,
// navigationOptions:{header:null}
},
Welcome:{
screen:WelcomeScreen,
// navigationOptions:{header:null}
},
Login:{
screen:Login,
},
Signup:{
screen:Signup,
// navigationOptions:{header:null}
},
},
{
headerMode:'none',
initialRouteName: "Walkthorugh",
cardStyle: {backgroundColor: "transparent", opacity: 1 },
defaultNavigationOptions: {
gesturesEnabled: false,
cardStyle: {backgroundColor: "transparent", opacity: 1 },
swipeEnabled: false,
animationEnabled: false,
},
}
);
const AppContainer = createAppContainer(AppNavigator);
export default class App extends Component {
render() {
return (
<AppContainer />
)
}
}
And this is my Login.js ..
import React, { Component } from 'react';
import {
StyleSheet,
Platform,
View, ActivityIndicator, FlatList,
Text, Image, Dimensions, Keyboard, TextInput, ImageBackground,
StatusBar, TouchableOpacity
} from 'react-native';
import { NavigationActions, StackActions } from 'react-navigation';
const { width, height } = Dimensions.get('window');
const app_icon = require('./icons/app_icon.png')
const loginbg = require('./icons/loginbg.jpg')
const fashionbot = require('./icons/fashionbot.png')
import { Api_const, App_colors } from './Const/Const.js';
import { ScrollView } from 'react-native-gesture-handler';
import LinearGradient from 'react-native-linear-gradient';
export default class Login extends Component {
static navigationOptions = {
headerTitle: 'Login',
// headerLeft: (
// <View style={{ flexDirection: "row", marginLeft: 20, marginRight: 20 }}>
// <TouchableWithoutFeedback>
// <Image source={require('../assets/Hamburger.png')} >
// </Image>
// </TouchableWithoutFeedback>
// </View>
// ),
headerStyle: { borderBottomWidth: 0, marginTop: (Platform.OS === 'ios') ? 0 : 0 },
headerBackTitle: " "
};
constructor(props) {
super(props);
this.state = {
isLoading: false,
email: '',
password: '',
}
}
onClick_Login = () => {
var action = StackActions.reset({
index: 0,
actions: [NavigationActions.navigate({ routeName: 'Home',params:{test:'test'} })]
});
this.props.navigation.dispatch(action);
// setTimeout(()=>{
// this.props.navigation.dispatch(action);
// },
// 400);
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator size="large" />
</View>
);
}
return (
<LinearGradient colors={[App_colors.purple, App_colors.pink, App_colors.pink]} style={{flex:1}}>
<ScrollView ref="scrollView" style={{ flex:1 }} bounces={false}>
<StatusBar hidden={true} backgroundColor={App_colors.purple} barStyle="dark-content" />
<View style={{ flex:1,height}}>
<ImageBackground source={loginbg} style={{height }}>
<View style={{height }}>
<View style={{ flexDirection: 'row', margin: 15 }}>
<Image style={{ flex: 0.3, height: 90, alignItems: 'center', justifyContent: 'center', alignSelf: 'center' }} resizeMode={"contain"} source={app_icon} />
<Image style={{ flex: 1, alignItems: 'center', justifyContent: 'center', alignSelf: 'center' }} resizeMode={"contain"} source={fashionbot} />
</View>
<View style={{flex:1, justifyContent: 'center', marginLeft: 25, marginRight: 25 }}>
<Text style={{ fontSize: 22, color: '#fff', alignItems: 'center', alignSelf: 'center' }}>{'Login'}</Text>
<Text style={{ fontSize: 16, color: '#fff', marginTop: 15 }}>{'Email'}</Text>
<TextInput style={{ fontSize: 14, height: 40, marginLeft: 0, marginRight: 0, color: 'white' }}
value={this.state.email}
onChangeText={(text) => this.setState({ email: text })}
placeholder={'Your Email'}
placeholderTextColor={App_colors.white}
underlineColorAndroid={'white'}
textContentType={'username'}
keyboardType='email-address'
caretHidden={false}
onSubmitEditing={() => { Keyboard.dismiss() }}
/>
{/* PASSWORD */}
<Text style={{ fontSize: 16, color: '#fff', marginTop: 15 }}>{'Password'}</Text>
<TextInput style={{ fontSize: 14, height: 40, marginLeft: 0, marginRight: 0, color: 'white' }}
value={this.state.password}
onChangeText={(text) => this.setState({ password: text })}
placeholder={'*********'}
placeholderTextColor={App_colors.white}
underlineColorAndroid={'white'}
secureTextEntry={true}
caretHidden={false}
onSubmitEditing={() => { Keyboard.dismiss() }}
/>
<Text style={{ fontSize: 16, color: '#fff', marginTop: 5 }}>{'Forgot Password?'}</Text>
<TouchableOpacity style={{ justifyContent: 'center',alignSelf:'center', marginBottom: 10, marginTop: 30, width: width - 100, marginLeft: 0, marginRight: 0, alignItems: 'center', borderRadius: 25, borderWidth: 0, paddingTop: 15, paddingBottom: 15, backgroundColor: 'white' }}
onPress={this.onClick_Login}>
<Text style={{ fontSize: 16, color: App_colors.purple }}>{'Log in'}</Text>
</TouchableOpacity>
</View>
</View>
</ImageBackground>
</View>
</ScrollView>
</LinearGradient>
);
}
}
in development mode react-native will show white screen. But in production, it won't so don't worry. it is normal.
about navigation I can't be sure but share the code or demo(image/video).

Hide TabNavigators and Header on Scroll

I want to hide the Header and the TabNavigator tabs onScroll. How do I do that? I want to hide them onScroll and show them on ScrollUp. My code:
import React, { Component } from 'react';
import { View, Text, ScrollView, StyleSheet, TouchableOpacity} from 'react-native';
class ScrollTest extends Component {
render(){
const { params } = this.props.navigation.state;
return(
<View style={styles.container}>
<ScrollView>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
<View style={{styles.newView}}><Text>Test</Text></View>
</ScrollView>
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1, padding:5
},
newView:{
height: 200, backgroundColor:'green', margin:10
}
})
export default ScrollTest;
I checked this link for Animated API but not able to figureout how to implement it in onScoll?
So the header HomeScreen and the tabs Tab1 and Tab2 should hide on scroll and show when scrolled up. How do I do that?
Please help getting started on this.
Many thanks.
I was also stuck with the same animation thing, I tried this code for maximizing and minimizing the header using the Animated API of react-native.
You can also do the same for showing and hiding it.
import React, { Component } from 'react';
import { Text, View, StyleSheet, ScrollView, Image,Animated } from 'react-native';
const HEADER_MAX_HEIGHT = 200;// set the initial height
const HEADER_MIN_HEIGHT = 60;// set the height on scroll
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
scrollY: new Animated.Value(0),
};
}
render() {
const headerHeight = this.state.scrollY.interpolate({
inputRange: [0, HEADER_SCROLL_DISTANCE],
outputRange: [HEADER_MAX_HEIGHT,HEADER_MIN_HEIGHT],
extrapolate: 'clamp',
});
return(
<View style={{flex: 1}}>
<ScrollView
scrollEventThrottle={1}
onScroll={Animated.event(
[{nativeEvent:
{contentOffset: {y: this.state.scrollY}}}]
)}>
<View style={styles.container}>
<Text style={styles.paragraph}>hello</Text>
<Image source={{uri: "https://static.pexels.com/photos/67843/splashing-splash-aqua-water-67843.jpeg"}} style={styles.imageStyle}/>
<Image source={{uri: "https://www.elastic.co/assets/bltada7771f270d08f6/enhanced-buzz-1492-1379411828-15.jpg" }}
style={styles.imageStyle}/>
</View>
</ScrollView>
<Animated.View style={[styles.footer, {height: headerHeight}]}>
<View style={styles.bar}>
<Text>text here</Text>
</View>
</Animated.View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: 24,
backgroundColor: '#ecf0f1',
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
color: '#34495e',
},
imageStyle: {
height: 360,
width: '100%',
},
footer: {
position:'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: 'red',
},
bar: {
alignItems: 'center',
justifyContent: 'center',
},
});
Hope this helps someone.
I resolved for my case, hope this will be helpful
import React from 'react';
import {
Animated,
Text,
View,
StyleSheet,
ScrollView,
Dimensions,
RefreshControl,
} from 'react-native';
import Constants from 'expo-constants';
import randomColor from 'randomcolor';
const HEADER_HEIGHT = 44 + Constants.statusBarHeight;
const BOX_SIZE = Dimensions.get('window').width / 2 - 12;
const wait = (timeout: number) => {
return new Promise((resolve) => {
setTimeout(resolve, timeout);
});
};
function App() {
const [refreshing, setRefreshing] = React.useState(false);
const scrollAnim = new Animated.Value(0);
const minScroll = 100;
const clampedScrollY = scrollAnim.interpolate({
inputRange: [minScroll, minScroll + 1],
outputRange: [0, 1],
extrapolateLeft: 'clamp',
});
const minusScrollY = Animated.multiply(clampedScrollY, -1);
const translateY = Animated.diffClamp(minusScrollY, -HEADER_HEIGHT, 0);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
wait(2000).then(() => {
setRefreshing(false);
});
}, []);
return (
<View style={styles.container}>
<Animated.ScrollView
contentContainerStyle={styles.gallery}
scrollEventThrottle={1}
bounces={true}
showsVerticalScrollIndicator={false}
style={{
zIndex: 0,
height: '100%',
elevation: -1,
}}
onScroll={Animated.event(
[{ nativeEvent: { contentOffset: { y: scrollAnim } } }],
{ useNativeDriver: true }
)}
overScrollMode="never"
contentInset={{ top: HEADER_HEIGHT }}
contentOffset={{ y: -HEADER_HEIGHT }}
refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />
}>
{Array.from({ length: 20 }, (_, i) => i).map((uri) => (
<View style={[styles.box, { backgroundColor: 'grey' }]} />
))}
</Animated.ScrollView>
<Animated.View style={[styles.header, { transform: [{ translateY }] }]}>
<Text style={styles.title}>Header</Text>
</Animated.View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
gallery: {
flexDirection: 'row',
flexWrap: 'wrap',
padding: 4,
},
box: {
height: BOX_SIZE,
width: BOX_SIZE,
margin: 4,
},
header: {
flex: 1,
height: HEADER_HEIGHT,
paddingTop: Constants.statusBarHeight,
alignItems: 'center',
justifyContent: 'center',
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: randomColor(),
},
title: {
fontSize: 16,
},
});
export default App;
checkout on Expo https://snack.expo.io/#raksa/auto-hiding-header

React-native elements search bar ref to use focus() method for instance is undefined

I followed the doc of the react-native-elements library but I get this.search as an undefined object...
searchbar react-native-elements
class SearchBarTest extends Component {
componentDidMount()
{
this.search.focus()//search is undefined
}
render(){
<SearchBar
ref={search => this.search = search}
...
/>
}
}
Any idea how to make this working?
EDIT:
Adding full context of the code.
The idea is having a component with a header and body. The header has an optional search bar or a title and two buttons depending on the props search.
If search props is true, then I display the searchBar.
PARENT COMPONENT:
import React, {Component} from 'react';
import {StyleSheet, View, Text, TouchableWithoutFeedback, Keyboard} from 'react-native';
import Icon from 'react-native-vector-icons/Ionicons';
import DismissableKeyboardContainer from '../../components/DismissableKeyboardContainer';
export default class Search extends Component {
static navigationOptions = () => {
return {
tabBarIcon: ({tintColor}) => (
<Icon name="ios-search-outline" size={25} color={tintColor}/>
)
}
};
render() {
someMethod = () => {
console.log('hello');
}
return (
<DismissableKeyboardContainer search={true}>
<View style={{flex: 1, alignItems: 'center'}}>
<Text>Hello world</Text>
</View>
</DismissableKeyboardContainer>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
}
});
COMPONENT where the actual searchBar component is used:
import React, { Component} from 'react';
import { Keyboard, TouchableWithoutFeedback, TouchableOpacity, View, Text, StyleSheet} from 'react-native';
import { SearchBar } from 'react-native-elements'
import Icon from 'react-native-vector-icons/Ionicons';
import PropTypes from 'prop-types';
class DismissableKeyboardContainer extends Component {
static defaultProps = {
title: '',
search: false,
buttonLeft: '',
buttonRight: '',
borderShadow: true,
headerStyle:{}
};
componentDidMount()
{
}
render() {
let { title, search, buttonLeft, buttonRight, headerStyle, borderShadow } = this.props;
return (
<TouchableWithoutFeedback onPress={() => Keyboard.dismiss()}>
<View style={{ flex: 1 }}>
<View style={[styles.headerContainer, borderShadow ? styles.borderShadow : '', headerStyle]}>
{
!search && <View style={{position: 'absolute', padding: 10, bottom: 0, flex: 1, flexDirection: 'row', alignItems: 'center', justifyContent: 'center'}}>
<TouchableOpacity style={{ flex: 0.2, alignItems: 'center'}}>
{
buttonLeft != "" && <Icon name={buttonLeft} size={25} color="grey" />
}
</TouchableOpacity>
<View style={{ flex: 1, alignItems: 'center' }}>
<Text style={styles.title}>{title}</Text>
</View>
<TouchableOpacity style={{ flex: 0.2, alignItems: 'center' }}>
{
buttonRight != "" && <Icon name={buttonRight} size={25} color="grey" />
}
</TouchableOpacity>
</View>
}
{
search && <SearchBar
ref={search => this.search = search}
containerStyle={{ backgroundColor: 'transparent', borderTopWidth: 0, borderBottomWidth: 0 }}
inputStyle={{ backgroundColor: 'white' }}
lightTheme
onChangeText={someMethod}
placeholder='Type Here...'
/>
}
</View>
<View style={{ flex: 1, backgroundColor: 'transparent'}}>
{this.props.children}
</View>
</View>
</TouchableWithoutFeedback>
);
}
}
const styles = StyleSheet.create({
headerContainer: {
flex: 0.12,
justifyContent: 'flex-end',
backgroundColor: 'white' ,
},
borderShadow: {
borderColor: '#ddd',
borderBottomWidth: 0,
shadowColor: '#000',
shadowOffset: { width: 0, height: 2 },
shadowOpacity: 0.2,
shadowRadius: 1,
elevation: 1,
},
title: {
fontSize: 18,
fontWeight: 'bold'
}
});
DismissableKeyboardContainer.propTypes = {
title: PropTypes.string.isRequired,
search: PropTypes.bool.isRequired,
buttonLeft: PropTypes.string.isRequired,
buttonRight: PropTypes.string.isRequired,
headerStyle: PropTypes.any,
};
export default DismissableKeyboardContainer;
I think I found the issue. As my SearchScreen is part of a TabBar from react-navigation, this.search.focus() error was appearing at the initial loading of the app. The Search screen being the second tab of the tabBar, I guess this is the reason why search couldn't be found as the screen was not active.
Found this answer: Trigger event on tabBar screen display
Which helped me to launch the this.search.focus() only when the screen Search is called under the componentDidUpdate() method
Please see code below:
1- First on my root navigator, I track react-navigation screen changes with onNavigationStateChange and screenProps
<Root
onNavigationStateChange={(prevState, currentState, action) => {
let currentScreen = action.routeName;
this.setState({ currentScreen })
}}
screenProps={{ currentScreen: this.state.currentScreen }}
/>
2- Then on my Parent component, I pass the currentScreen prop from I setup above in react-navigation
<DismissableKeyboardContainer search={true} currentScreen={this.props.screenProps.currentScreen}>
<View style={{flex: 1, alignItems: 'center'}}>
<Text>Hello world</Text>
</View>
</DismissableKeyboardContainer>
3- Now, I'm checking the screen being displayed and launch this.search.focus() only if the screen Search is displayed inside my DismissableKeyboardContainer child component.
componentDidUpdate() {
this.props.currentScreen === "Search" ? this.search.focus() : ''
}