React Native: How to pass data from screen to another? - javascript

in my AuthNavigator is onAuthChanged so it renders my AppStack when someone is logged in. Now i need the User ID from the logged in person in my Ingredients Screen. And this Ingredients Screen is a Stacknavigator inside of a Tabnavigator. So how can i pass the data from my user var to the Ingredients Screen.
AuthNavigator File:
import React, { useState, useEffect, createContext } from "react";
import firebase from "./firebase";
import AppStack from "./stacks/AppStack";
import AuthStack from "./stacks/AuthStack";
export const AuthContext = createContext(null);
export default function AuthNavigator() {
const [initializing, setInitializing] = useState(true);
const [user, setUser] = useState(true);
// Handle user state changes
async function onAuthStateChanged(result) {
setUser(result);
if (initializing) setInitializing(false);
console.log(user.uid)
var userDoc = await firebase.firestore().doc("users/" + user.uid).get();
if (!userDoc.exists) {
await userDoc.ref.set({
email: user.email,
uid: user.uid
})
}
}
useEffect(() => {
const authSubscriber = firebase
.auth()
.onAuthStateChanged(onAuthStateChanged);
// unsubscribe on unmount
return authSubscriber;
}, []);
if (initializing) {
return null;
}
return user ? (
<AuthContext.Provider value={user}>
<AppStack user={user} />
</AuthContext.Provider>
) : (
<AuthStack />
);
}
AppStack
import React, { lazy } from "react";
import News from "../screens/News";
import Favorites from "../screens/Favorites";
import NewRecipe from "../screens/NewRecipe";
import Ingredients from "../screens/Ingredients";
import Profile from "../screens/Profile";
import { NavigationContainer, DarkTheme } from "#react-navigation/native";
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
import { MaterialIcons } from "#expo/vector-icons";
import { createStackNavigator } from "#react-navigation/stack";
import { AuthContext } from "../AuthNavigator"
export default function AppStack() {
const Tab = createBottomTabNavigator();
const NewsStack = createStackNavigator();
const FavoritesStack = createStackNavigator();
const NewRecipeStack = createStackNavigator();
const IngredientsStack = createStackNavigator();
const ProfileStack = createStackNavigator();
function NewsNav() {
return (
<NewsStack.Navigator>
<NewsStack.Screen
name="News"
component={News}
options={{
headerTintColor: "#AD1457",
headerStyle: {
backgroundColor: "#171717",
height: 75,
},
headerTitleStyle: {
marginTop: -15,
},
}}
/>
</NewsStack.Navigator>
);
}
function FavoritesNav() {
return (
<FavoritesStack.Navigator>
<FavoritesStack.Screen
name="Favoriten"
component={Favorites}
options={{
headerTintColor: "#AD1457",
headerStyle: {
backgroundColor: "#171717",
height: 75,
},
headerTitleStyle: {
marginTop: -15,
},
}}
/>
</FavoritesStack.Navigator>
);
}
function NewRecipeNav() {
return (
<NewRecipeStack.Navigator mode="card">
<NewRecipeStack.Screen
name="Neue Rezepte"
component={NewRecipe}
options={{
headerTintColor: "#AD1457",
headerStyle: {
backgroundColor: "#171717",
height: 75,
},
headerTitleStyle: {
marginTop: -15,
},
}}
/>
</NewRecipeStack.Navigator>
);
}
function IngredientsNav(props) {
return (
<IngredientsStack.Navigator>
<IngredientsStack.Screen
name="Zutaten"
component={Ingredients}
options={{
headerTintColor: "#AD1457",
headerStyle: {
backgroundColor: "#171717",
height: 75,
},
headerTitleStyle: {
marginTop: -15,
},
}}
/>
</IngredientsStack.Navigator>
);
}
function ProfileNav() {
return (
<ProfileStack.Navigator >
<ProfileStack.Screen
name="Profil"
component={Profile}
options={{
headerTintColor: "#AD1457",
headerStyle: {
backgroundColor: "#171717",
height: 75,
},
headerTitleStyle: {
marginTop: -15,
},
}}
/>
</ProfileStack.Navigator >
);
}
return (
<NavigationContainer>
<AuthContext.Consumer value={user}>
<Tab.Navigator
tabBarOptions={{
style: {
backgroundColor: '#171717',
borderTopColor: '#121212'
},
inactiveTintColor: '#fff',
activeTintColor: '#AD1457',
}}
initialRouteName="News"
screenOptions={({ route }) => ({
tabBarIcon: ({ color }) => {
let iconName;
if (route.name == "News") {
iconName = "language";
} else if (route.name == "Favoriten") {
iconName = "star-border";
} else if (route.name == "Hinzufügen") {
iconName = "add-circle-outline";
} else if (route.name == "Zutaten") {
iconName = "shopping-cart";
} else if (route.name == "Profil") {
iconName = "person";
}
return (
<MaterialIcons
name={iconName}
color={color}
size={25}
></MaterialIcons>
);
},
})}
>
<Tab.Screen name="News" component={NewsNav} />
<Tab.Screen name="Favoriten" component={FavoritesNav} />
<Tab.Screen name="Hinzufügen" component={NewRecipeNav} />
<Tab.Screen name="Zutaten" component={IngredientsNav} />
<Tab.Screen name="Profil" component={ProfileNav} />
</Tab.Navigator>
</AuthContext.Consumer>
</NavigationContainer >
);
}
Ingredients Screen File:
import React, { useState } from "react";
import { View, Text, StyleSheet, TextInput, ImageBackground, ActivityIndicator } from "react-native";
import { SafeAreaView } from "react-native-safe-area-context";
import { FlatList, TouchableOpacity } from "react-native-gesture-handler";
import { AntDesign, Ionicons, Feather } from '#expo/vector-icons';
import firebase from "../firebase"
import { user } from '../AuthNavigator'
export default function Ingredients(props) {
const [isLoading, setIsLoading] = useState(false);
const ingredientsList = [
]
const [userIngredientsList, setUserIngredientsList] = useState(ingredientsList);
function handleRemoveItem(id, label) {
const newList = userIngredientsList.filter((item) => item.id !== id);
setUserIngredientsList(newList);
window.alert("Die Zutat " + (label) + " wurde gelöscht")
}
var appId = "20b96f8f",
appKey = "aebde7ed85b4aec1f50d3cbe4ff4f165";
async function fetchIngredient(searchValue) {
setIsLoading(true);
var request = new XMLHttpRequest();
request.open("GET", "https://api.edamam.com/api/food-database/v2/parser?app_id=" + appId + "&app_key=" + appKey + "&ingr=" + searchValue);
request.addEventListener('load', function (event) {
if (request.status >= 200 && request.status < 300) {
var food = JSON.parse(request.responseText).parsed[0].food;
console.log(user.uid)
var newItem = {
id: food.foodId,
label: searchValue,
image: food.image,
amount: 1
};
var found = false
userIngredientsList.forEach((item, index) => {
if (item.id == newItem.id) {
newItem.amount = item.amount + 1
userIngredientsList.splice(index, 1)
}
})
setUserIngredientsList(ingredientsList => [newItem, ...ingredientsList]);
setIsLoading(false);
setSearchValue('');
firebase.firestore().doc("ingredients/" + props.user.uid).set({
ingredients: userIngredientsList
})
}
else {
setIsLoading(false);
window.alert('Gibt es nicht')
}
});
request.send();
}
const renderItem = ({ item }) => (
<View style={styles.item} >
<View>
<ImageBackground source={{ uri: item.image }}
style={styles.itemBackground}
imageStyle={{ borderTopRightRadius: 18, borderBottomRightRadius: 18, opacity: 0.4 }}
resizeMode="cover">
<TouchableOpacity onPress={() => handleRemoveItem(item.id, item.label)}>
<AntDesign style={styles.iconDelete} name="delete" size={30} color="black" />
</TouchableOpacity>
</ImageBackground >
</View>
<View style={styles.itemInfo}>
<Text style={styles.itemTitle}>{item.title}</Text>
<Feather style={styles.iconTime} name="clock" size={30} color='#fff' />
<Text style={styles.itemCookingTime}>~ {item.time} min</Text>
<Text style={{ color: '#fff' }}>{item.amount} </Text>
</View>
</View >
)
const [searchValue, setSearchValue] = useState('');
return (
<View style={styles.container}>
<View style={styles.searchBar}>
<View style={{ alignSelf: "flex-end", marginTop: 8, marginRight: 30 }}>
<TouchableOpacity onPress={async () => await fetchIngredient(searchValue)}>
{!isLoading && <Ionicons name="md-add" size={32} color="#fff" />}
</TouchableOpacity>
{isLoading && <ActivityIndicator style={styles.loading} color='#AD1457' />}
</View>
{!isLoading && <TextInput style={{
alignSelf: "flex-start", marginLeft: 25, marginTop: -30, fontSize: 20, color: '#fff', width: 200
}} placeholder="Suche" placeholderTextColor='#fff' value={searchValue} onChangeText={(searchValue) => setSearchValue(searchValue)}></TextInput>}
</View>
<FlatList
data={userIngredientsList}
renderItem={renderItem}
keyExtractor={(item) => item.id}>
</FlatList>
</View >
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: "#121212",
},
item: {
flex: 1,
width: 350,
height: 200,
marginTop: 50,
alignSelf: "center",
borderWidth: 2,
borderRadius: 20,
borderColor: '#AD1457'
},
itemBackground: {
width: 174,
height: 196,
alignSelf: "flex-end",
backgroundColor: 'rgba(255,255,255,0.2)',
borderTopRightRadius: 18,
borderBottomRightRadius: 18
},
itemInfo: {
marginTop: -174,
width: 174,
height: 196,
alignSelf: "flex-start",
borderTopRightRadius: 18,
borderBottomRightRadius: 18
},
itemTitle: {
color: '#fff',
fontSize: 18,
alignSelf: "flex-start",
marginLeft: 35
},
iconTime: {
alignSelf: "flex-start",
marginLeft: 35,
marginTop: 75
},
itemCookingTime: {
marginLeft: 80,
fontSize: 18,
color: '#fff',
marginTop: -30
},
iconDelete: {
alignSelf: "flex-end",
marginRight: 25,
marginTop: 25,
color: '#fff'
},
checkCircle: {
alignSelf: "flex-end",
marginRight: 25,
marginTop: 85,
color: "#00FF44"
},
searchBar: {
backgroundColor: '#313131',
width: 325,
height: 50,
borderRadius: 25,
color: '#fff',
fontSize: 20,
marginTop: 25
},
loading: {
alignSelf: "flex-end",
marginTop: 8,
}
});

I fixed with simply using the useContext(AuthContext);

Related

Problem to show my images from backend in the mobile

I'm using react native. The images are in svg, so I'm using "react-native-svg" library. The images are working normally in the web, but when I try to show in mobile appear this crazy error:
Expected closing tag </head> to match opening tag <meta> (6:4). If this is valid SVG, it's probably a bug. Please raise an issue
</head>
^
Here where I'm trying to show the images:
<View style={styles.itemsContainer}>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={{paddingHorizontal: 20}}
>
{items.map(item => (
<TouchableOpacity
key={String(item.id)}
style={[
styles.item,
selectedItems.includes(item.id) ? styles.selectedItem : {}
]}
onPress={() => handleSelectItem(item.id)}
activeOpacity={0.6}
>
<SvgUri width={42} height={42} uri={item.image_url}/>
<Text style={styles.itemTitle}>{item.name}</Text>
</TouchableOpacity>
))}
</ScrollView>
</View>
This is the entire code:
import React, {useState, useEffect} from 'react'
import {View, StyleSheet, TouchableOpacity, Text, ScrollView, Image, Alert} from "react-native";
import {Feather as Icon} from '#expo/vector-icons';
import {useNavigation, useRoute} from '#react-navigation/native';
import Constants from 'expo-constants';
import api from '../../services/api';
import MapView, {Marker} from 'react-native-maps';
import {SvgUri} from 'react-native-svg';
import * as Location from 'expo-location';
interface Item {
id: number;
name: string;
image_url: string
}
interface Point {
id: number;
name: string;
image: string;
latitude: number;
longitude:number;
image_url: string;
}
interface Params {
uf: string,
city: string,
}
const Points = () => {
const navigation = useNavigation();
const [items, setItems] = useState<Item[]>([]);
const [selectedItems, setSelectedItems] = useState<number[]>([]);
const [initialPosition, setInitialPosition] = useState<[number, number]>([0, 0]);
const [points, setPoints] = useState<Point[]>([]);
const route = useRoute();
const routeParams = route.params as Params;
useEffect(() => {
api.get('items').then(response => {
setItems(response.data);
});
}, []);
useEffect(() => {
async function loadPosition() {
const { status } = await Location.requestPermissionsAsync();
if (status !== 'granted') {
Alert.alert('Oooops...', 'precisamos de sua permissão para mostrarmos sua localização');
return ;
}
const location = await Location.getCurrentPositionAsync();
const { latitude, longitude } = location.coords;
setInitialPosition([
latitude,
longitude
]);
}
loadPosition();
}, []);
useEffect(() => {
api.get('points', {
params: {
city: routeParams.city,
uf: routeParams.uf,
items: selectedItems,
},
}).then((response) => {
setPoints(response.data)
})
}, [selectedItems]);
function handleNavigateBack() {
navigation.goBack();
}
function handleNavigateToDetail(id: number) {
navigation.navigate('Detail', { point_id: id})
}
function handleSelectItem(id: number) {
const alreadySelected = selectedItems.findIndex(item => item === id );
if (alreadySelected >= 0) {
const filteredItems = selectedItems.filter(item => item !== id);
setSelectedItems(filteredItems)
} else {
setSelectedItems([...selectedItems, id])
}
}
return (
<>
< View style={styles.container}>
<TouchableOpacity onPress={handleNavigateBack}>
<Icon name="arrow-left" size={20} color="#34cb79"/>
</TouchableOpacity>
<Text style={styles.title}>Bem Vindo.</Text>
<Text style={styles.description}>Encontre no mapa um ponto de coleta</Text>
<View style={styles.mapContainer}>
{ initialPosition[0] !== 0 && (
<MapView
style={styles.map}
loadingEnabled={initialPosition[0] === 0}
initialRegion={{
latitude: initialPosition[0],
longitude: initialPosition[1],
latitudeDelta: 0.014,
longitudeDelta: 0.014 ,
}} >
{points.map(point => (
<Marker
key={String(point.id)}
style={styles.mapMarker}
onPress={() => handleNavigateToDetail(point.id)}
coordinate={{
latitude: point.latitude,
longitude: point.longitude,
}}>
<View style={styles.mapMarkerContainer}>
<Image style={styles.mapMarkerImage} source={{uri: point.image_url}}/>
<Text style={styles.mapMarkerTitle}>{point.name}</Text>
</View>
</Marker>
))}
</MapView>
) }
</View>
</View>
<View style={styles.itemsContainer}>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
contentContainerStyle={{paddingHorizontal: 20}}
>
{items.map(item => (
<TouchableOpacity
key={String(item.id)}
style={[
styles.item,
selectedItems.includes(item.id) ? styles.selectedItem : {}
]}
onPress={() => handleSelectItem(item.id)}
activeOpacity={0.6}
>
<SvgUri width={42} height={42} uri={item.image_url}/>
<Text style={styles.itemTitle}>{item.name}</Text>
</TouchableOpacity>
))}
</ScrollView>
</View>
</>
)
};
const styles = StyleSheet.create({
container: {
flex: 1,
paddingHorizontal: 32,
paddingTop: 20 + Constants.statusBarHeight,
},
title: {
fontSize: 20,
fontFamily: 'Ubuntu_700Bold',
marginTop: 24,
},
description: {
color: '#6C6C80',
fontSize: 16,
marginTop: 4,
fontFamily: 'Roboto_400Regular',
},
mapContainer: {
flex: 1,
width: '100%',
borderRadius: 10,
overflow: 'hidden',
marginTop: 16,
},
map: {
width: '100%',
height: '100%',
},
mapMarker: {
width: 90,
height: 80,
},
mapMarkerContainer: {
width: 90,
height: 70,
backgroundColor: '#34CB79',
flexDirection: 'column',
borderRadius: 8,
overflow: 'hidden',
alignItems: 'center'
},
mapMarkerImage: {
width: 90,
height: 45,
resizeMode: 'cover',
},
mapMarkerTitle: {
flex: 1,
fontFamily: 'Roboto_400Regular',
color: '#FFF',
fontSize: 13,
lineHeight: 23,
},
itemsContainer: {
flexDirection: 'row',
marginTop: 16,
marginBottom: 32,
},
item: {
backgroundColor: '#fff',
borderWidth: 2,
borderColor: '#eee',
height: 120,
width: 120,
borderRadius: 8,
paddingHorizontal: 16,
paddingTop: 20,
paddingBottom: 16,
marginRight: 8,
alignItems: 'center',
justifyContent: 'space-between',
textAlign: 'center',
},
selectedItem: {
borderColor: '#34CB79',
borderWidth: 2,
},
itemTitle: {
fontFamily: 'Roboto_400Regular',
textAlign: 'center',
fontSize: 13,
},
});
export default Points;

how to focus / blur event on button list react native

I'm trying to emulate focus/ blur event in react native with no success. I have two components, Home and Button. In home i render a list of buttons(category1, category2 and category3).
Here is my code:
---HOME COMPONENT----
state = {
categories: ['category1', 'category2', 'category3']
};
renderCategories() {
return this.state.categories.map((category, index) => (
<Button onPress={() => this.getCategories(category)} key={index}>
{category}
</Button>
));
}
render() {
return (
<View>
<ScrollView horizontal showsHorizontalScrollIndicator={false} style={{marginBottom: 5}}>
{this.renderCategories()}
</ScrollView>
</View>
)
}
---BUTTON COMPONENT---
class Button extends Component {
constructor(props) {
super(props);
this.state = { pressStatus: false };
}
_onHideUnderlay() {
this.setState({ pressStatus: false });
console.log('unpressed')
}
_onShowUnderlay() {
this.setState({ pressStatus: true });
console.log('pressed')
}
render () {
const {buttonStyle, buttonPressedStyle, textStyle} = styles;
return (
<TouchableHighlight onPress={this.props.onPress}
underlayColor={'#fff000'}
activeOpacity={1}
style={[buttonStyle, this.state.pressStatus ? {backgroundColor: '#fff000'} : {backgroundColor: '#1D36FF'}]}
// onHideUnderlay={this._onHideUnderlay.bind(this)}
onShowUnderlay={this._onShowUnderlay.bind(this)}>
<Text style={textStyle}>
{this.props.children}
</Text>
</TouchableHighlight>
);
}
}
const styles = {
buttonStyle: {
marginTop:10,
paddingTop:15,
paddingBottom:25,
marginLeft:10,
// marginRight:10,
paddingLeft: 15,
paddingRight: 15,
backgroundColor:'rgba(99,99,99,0.99)',
borderRadius:10,
borderWidth: 1,
borderColor: '#fff'
},
buttonPressedStyle: {
marginTop:10,
paddingTop:15,
paddingBottom:25,
marginLeft:10,
// marginRight:10,
paddingLeft: 15,
paddingRight: 15,
backgroundColor:'rgba(15,15,15,0.99)',
borderRadius:10,
borderWidth: 1,
borderColor: '#fff'
},
textStyle: {
color:'#fff',
textAlign:'center',
fontSize: 16
},
};
This code works partially. When i click first button(category1) it changes the background color as expected, but when i click second button(category2) then the button category1 should take the initial style(lost focus).
Please help. Thanks
#Aramillo, You are facing this issue because you are using same property value pressStatus for all the three buttons.
Do it in some different manner.
Please try below code -
in App.js
import React, { Component } from "react";
import { ScrollView, Text, View } from "react-native";
import Button from "./Button";
class App extends Component {
constructor(props) {
super(props);
this.state = {
pressedButton: null,
categories: ["category1", "category2", "category3"]
};
}
getCategories = (category, index) => {
this.setState({ pressedButton: index });
};
renderCategories() {
return this.state.categories.map((category, index) => (
<Button
onPress={() => this.getCategories(category, index)}
buttonId={index}
pressedButton={this.state.pressedButton}
key={index}
>
<Text>{category}</Text>
</Button>
));
}
render() {
return (
<View>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={{ marginBottom: 5 }}
>
{this.renderCategories()}
</ScrollView>
</View>
);
}
}
export default App;
In Button.js
import React, { Component } from "react";
import { TouchableHighlight, Text } from "react-native";
class Button extends Component {
constructor(props) {
super(props);
this.state = { pressStatus: false };
}
onHideUnderlay() {
this.setState({ pressStatus: false });
console.log("unpressed");
}
_onShowUnderlay() {
this.setState({ pressStatus: true });
console.log("pressed");
}
render() {
const { buttonStyle, textStyle } = styles;
return (
<TouchableHighlight
onPress={this.props.onPress}
underlayColor={"#fff000"}
activeOpacity={1}
style={[
buttonStyle,
this.props.buttonId === this.props.pressedButton
? { backgroundColor: "#fff000" }
: { backgroundColor: "#1D36FF" }
]}
// onHideUnderlay={this._onHideUnderlay.bind(this)}
onShowUnderlay={this._onShowUnderlay.bind(this)}
>
<Text style={textStyle}>{this.props.children}</Text>
</TouchableHighlight>
);
}
}
export default Button;
const styles = {
buttonStyle: {
marginTop: 10,
paddingTop: 15,
paddingBottom: 25,
marginLeft: 10,
// marginRight:10,
paddingLeft: 15,
paddingRight: 15,
backgroundColor: "rgba(99,99,99,0.99)",
borderRadius: 10,
borderWidth: 1,
borderColor: "#fff"
},
buttonPressedStyle: {
marginTop: 10,
paddingTop: 15,
paddingBottom: 25,
marginLeft: 10,
// marginRight:10,
paddingLeft: 15,
paddingRight: 15,
backgroundColor: "rgba(15,15,15,0.99)",
borderRadius: 10,
borderWidth: 1,
borderColor: "#fff"
},
textStyle: {
color: "#fff",
textAlign: "center",
fontSize: 16
}
};
Working example here - https://codesandbox.io/s/empty-currying-cikw4

How i make the same table model (without the words contents) in react native/expo as my picture example

how I make the same table model (i need the same table without the contents) in react-native/expo as my picture examples?
I try so many things but its doesn't work for me and i need some help with that.
here you can see my example the first picture and I want to transfer it to the example as the second picture.
this is the example table that i have now:
this is the example table that i want :
this is my code :
import React, { Component } from "react";
import {
View,
Text,
StyleSheet,
ActivityIndicator,
Platform,
FlatList,
TouchableOpacity,
Dimensions
} from "react-native";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/HeaderButton";
import axios from "axios";
import { Card } from "react-native-elements";
import { Icon } from "react-native-elements";
const { width, height } = Dimensions.get('window');
export default class MainScreen extends Component {
constructor(props) {
super(props);
this.state = { data: [] };
}
getData = () => {
this.setState({ isLoading: true, data: [] })
axios.get("https://rallycoding.herokuapp.com/api/music_albums ")
.then(res => {
this.setState({
isLoading: false,
data: res.data
});
console.log(res.data);
});
}
componentDidMount() {
this.props.navigation.setParams({ getData: this.getData });
this.getData()
}
renderItem(item) {
const { title, artist} = item.item;
return (
<TouchableOpacity
onPress={() => this.props.navigation.navigate("Settings")}
>
<View style={styles.itemView}>
<View style={styles.itemInfo}>
<Text style={styles.name}>
{title+ ' ' + artist}
</Text>
<Text style={styles.vertical} numberOfLines={1}>{artist} |</Text>
</View>
</View>
</TouchableOpacity>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{ flex:0,paddingTop: 300 }}>
<Text style={{ alignSelf: "center", fontWeight: "bold", fontSize: 20 }}>loading data...</Text>
<ActivityIndicator size={'large'} color={'#08cbfc'} />
</View>
);
}
return (
<>
<View style={styles.container}>
<FlatList
data={this.state.data}
renderItem={this.renderItem.bind(this)}
keyExtractor={(_, index) => String(index)}
/>
{/* <Text>{this.state.data.length !== 0 ? this.state.data.length : "NO DATA FOUND" }</Text> */}
</View>
<View style={styles.bottomMainContainer}>
<View style={styles.bottomView} >
<Text style={styles.bottomTextStyle}>סה"כ: {this.state.data.length} רשומות</Text>
</View>
</View>
</>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 0,
justifyContent: 'center',
alignItems: 'center',
// backgroundColor:'pink'
},
itemView: {
flex: 1,
width,
borderBottomWidth: 0.5,
borderColor: 'black',
borderStyle: 'solid',
paddingHorizontal: 12,
flexDirection: 'row',
},
imgContainer: {
// flex: 0,
// borderColor: 'black',
// borderWidth: 1.5,
// height: 60,
// width: 60,
// alignItems: 'center',
// justifyContent: 'center',
},
itemInfo: {
flex: 1,
marginHorizontal: 10,
// backgroundColor:'pink'
},
name: {
//fontFamily: 'Verdana',
fontSize: 18,
color: '#ff0000',
textAlign: 'left',
},
vertical: {
fontSize: 18,
}

React functional bases props is not defined

i need your helps.
I have a functional based component call WelcomeSlidePage. I want to pass a functional to the functional component. i try to console.log the function in functional component, in the first state, console.log is printing the function, but after the second state, it's becomes undefine.
this is my component that calling the functional component
WebViewPage.jsx
<Modal transparent={true} visible={this.state.WelcomeSlidePageModal} animationType="
<WelcomeSlidePage onDone={()=>{console.log('test bro');this.setState({WelcomeSlidePageModal:false})}}/>
</Modal>
and this is my functional component
WelcomeSlidePage.jsx
import React, { useState, useEffect } from 'react';
import { StyleSheet, View, Text, Image, TouchableOpacity } from 'react-native';
import AppIntroSlider from 'react-native-app-intro-slider';
import string from '../string'
import { _storeData, _getData } from '../components/StoreAsync';
export default WelcomeSlide = (props) => {
const [language, setLanguage] = useState('english');
const [showRealApp, setShowRealApp] = useState(false);
const welcomeSlide = string.welcome_slide[language]
useEffect(() => {
console.log('testing bro',props.onDone)
// getData();
});
async function getData() {
setLanguage( await _getData("language"));
setShowRealApp( await _getData("showRealApp"));
}
_renderItem = ({ item }) => {
switch (item.key) {
case ('k4'):
return (
<View style={{backgroundColor : '#a0c83a', flex: 1}}>
<Text style={styles.title}>{item.title}</Text>
<View style={{justifyContent: 'center', paddingHorizontal: 20, flex: 1}}>
<Text style={styles.text}>{item.text_4_a}</Text>
<View style={{flexDirection: 'row'}}>
<Image style={styles.icon} source={item.icon} />
<Text style={{paddingStart: 5, paddingEnd: 20, ...styles.text}}>{item.text_4_b}</Text>
</View>
<Text style={styles.text}>{item.text_4_c}</Text>
<View style={{flexDirection: 'row'}}>
<Image style={styles.icon} source={item.icon} />
<Text style={{paddingStart: 5, paddingEnd: 20, ...styles.text}}>{item.text_4_d}</Text>
</View>
</View>
</View>
);
case ('k5'):
return (
<View style={styles.slide}>
<Text style={styles.title}>{item.text_5}</Text>
<TouchableOpacity style={{marginVertical: 24}} onPress={()=>{ props.navigation.navigate('WebView', { url: string.onboarding[language].login_url }); }}>
<Text style={styles.button}>{item.text_5_btn1}</Text>
</TouchableOpacity>
<TouchableOpacity style={{marginVertical: 24}} onPress={()=>{ props.navigation.navigate('WebView', { url: string.onboarding[language].register_url }); }}>
<Text style={styles.button}>{item.text_5_btn2}</Text>
</TouchableOpacity>
</View>
);
default:
return (
<View style={styles.slide}>
<Text style={styles.title}>{item.title}</Text>
<Image style={styles.image} source={item.image} />
<Text style={{paddingHorizontal: 20, ...styles.text}}>{item.text}</Text>
</View>
);
}
}
_onDone = () => {
setShowRealApp(true);
_storeData('isPassSlide',true);
props.navigation.navigate('WebView', { url: string.onboarding[language].login_url,splashScreen:false });
}
const slides = [
{
key: 'k1',
title: welcomeSlide.title,
text: welcomeSlide.a,
image: require('../images/my_library_card_white_notext_nopadding.png'),
backgroundColor: '#a0c83a',
},
{
key: 'k2',
title: welcomeSlide.title,
text: welcomeSlide.b,
image: require('../images/my_account_white_notext_nopadding.png'),
backgroundColor: '#a0c83a',
},
{
key: 'k3',
title: welcomeSlide.title,
text: welcomeSlide.c,
image: require('../images/library_catalog_white_notext_nopadding.png'),
backgroundColor:'#a0c83a',
},
{
key: 'k4',
title: welcomeSlide.title,
text_4_a: welcomeSlide.d_a,
text_4_b: welcomeSlide.d_b,
text_4_c: welcomeSlide.d_c,
text_4_d: welcomeSlide.d_d,
icon: require('../images/icon-hand-right.png'),
backgroundColor: '#a0c83a',
},
{
key: 'k5',
text_5: welcomeSlide.e,
text_5_btn1: welcomeSlide.e_btn1,
text_5_btn2: welcomeSlide.e_btn2,
backgroundColor:'#a0c83a',
},
];
return(
<AppIntroSlider
renderItem={_renderItem}
prevLabel={string.back[language]}
nextLabel={string.next[language]}
doneLabel={string.next[language]}
showPrevButton={true}
slides={slides}
onDone={()=>props.onDone()}/>
)
}
const styles = StyleSheet.create({
slide : {
flex: 1,
paddingTop: (Platform.OS) === 'ios' ? 20 : 0,
paddingBottom: 80,
backgroundColor : '#a0c83a',
alignItems: 'center',
},
title: {
fontSize: 24,
color: '#fff',
fontWeight: 'bold',
textAlign: 'center',
marginTop : 30,
},
text: {
fontSize : 20,
color: '#fff',
textAlign: 'left',
},
image: {
width: 200,
height: 200,
resizeMode: 'contain',
flex:1,
},
icon: {
top: 10,
width: 25,
height: 15,
width: 25,
marginTop: -3,
},
content: {
paddingHorizontal: 20,
},
button: {
borderRadius: 8,
paddingVertical: 12,
paddingHorizontal: 12,
color: 'white',
fontSize: 24,
fontWeight: 'bold',
textAlign: 'center',
marginHorizontal: 40,
backgroundColor: '#e46825',
shadowColor: '#000',
shadowOffset: { width: 0, height: 1 },
shadowOpacity: 0.8,
shadowRadius: 2,
elevation: 5,
},
});
and then this is the console log
testing bro function onDone() {
console.log('test bro');
_this2.setState({
WelcomeSlidePageModal: false
});
} b11b05fa-4e76-41da-9d58-218edc178e45:157683:15
testing bro undefined
please help me guys, thanks

undefined is not an object evaluating _this.props.navigation React Native

I am getting undefined is not an object evaluating _this.props.navigation. Here is my code.
I want to use the in multiple screens so I have to
extract it out and call it in any I need it in.
I have tried https://github.com/react-navigation/react-navigation/issues/2198#issuecomment-316883535 to no luck.
Category.js
import React, {Component} from 'react';
import {View, FlatList} from 'react-native';
import {ListItem} from 'react-native-elements'
import {AppRegistry, TouchableOpacity, ActivityIndicator} from 'react-native';
import {SearchHeader} from '../SearchHeader';
export default class Category extends Component {
constructor() {
super();
this.state = {
list: [],
};
this.onPress = this.onPress.bind(this);
}
static navigationOptions = {
title: 'Categories',
headerStyle: {backgroundColor: '#ffb30c'},
};
renderSeparator = () => {
return (
<View
style={{
height: 1,
width: "98%",
backgroundColor: "#CED0CE",
marginLeft: "1%",
marginRight: "1%"
}}
/>
);
};
_keyExtractor = (item, index) => item.name;
renderHeader = () => {
return (<SearchHeader />);
};
renderFooter = () => {
if (!this.state.loading) return null;
return (
<View
style={{
paddingVertical: 20,
borderTopWidth: 1,
borderColor: "#CED0CE"
}}
>
<ActivityIndicator animating size="large"/>
</View>
);
};
onPress = (item) => {
this.props.navigation.navigate('SpecTypeScreen',{cat:item});
};
search = () => {
};
render() {
return (
<FlatList
data={this.state.list}
renderItem={({item}) => (
<TouchableOpacity onPress={() => this.onPress(item)}>
<ListItem
title={`${item.name}`}
containerStyle={{borderBottomWidth: 0}}
/>
</TouchableOpacity>
)}
keyExtractor={this._keyExtractor}
ItemSeparatorComponent={this.renderSeparator}
ListHeaderComponent={this.renderHeader}
ListFooterComponent={this.renderFooter}
/>
);
}
}
AppRegistry.registerComponent('CategoryScreen', () => CategoryScreen);
SearchHeader.js
import React, {Component} from 'react';
import Autocomplete from 'react-native-autocomplete-input';
import {
AppRegistry,
View,
StyleSheet,
Platform,
Text,
TouchableOpacity,
} from 'react-native';
import {withNavigation} from 'react-navigation';
import colors from './config/colors';
import normalize from './config/normalizeText';
export class SearchHeader extends Component {
constructor() {
super();
this.state = {
list: [],
};
}
search = (term) => {
if (term.length > 2) {
fetch("https://myUrl?term=" + encodeURI(term))
.then((response) => response.json())
.then((responseJson) => {
this.setState({list: responseJson});
console.log(responseJson);
})
.catch((error) => {
console.error(error)
});
}
else{
this.setState({list: []});
}
};
onPress = (item) => {
this.props.navigation.navigate('ProductScreen',{spec:item});
};
render() {
return (
<View style={[
styles.container, styles.containerLight
]}>
<Autocomplete placeholder="Search Specs & Approvals..."
autoCorrect={false}
onChangeText={this.search}
data={this.state.list}
containerStyle={{backgroundColor: "#d71201"}}
inputStyle={{backgroundColor: "#fff"}}
renderItem={({ id, specification }) => (
<TouchableOpacity style={styles.autocompleteContainer} onPress={this.onPress.bind(this, specification)}>
<Text style={styles.itemText}>
{specification}
</Text>
<View
style={{
height: 1,
width: "98%",
backgroundColor: "#CED0CE",
marginLeft: "1%",
marginRight: "1%"
}}
/>
</TouchableOpacity>
)}
style={[
styles.input,
styles.inputLight,
{borderRadius: Platform.OS === 'ios' ? 15 : 20},
{paddingRight: 50}
]}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
borderTopWidth: 1,
borderBottomWidth: 1,
borderBottomColor: '#000',
borderTopColor: '#000',
backgroundColor: "#d71201",
maxHeight:70
},
containerLight: {
borderTopColor: '#e1e1e1',
borderBottomColor: '#e1e1e1',
},
input: {
paddingLeft: 26,
paddingRight: 19,
margin: 8,
borderRadius: 3,
overflow: 'hidden',
backgroundColor: colors.grey5,
fontSize: normalize(14),
color: colors.grey3,
height: 40,
...Platform.select({
ios: {
height: 30,
},
android: {
borderWidth: 0,
},
}),
},
inputLight: {
backgroundColor: "#fff"
},
autocompleteContainer: {
backgroundColor:"#fff",
marginLeft: 10,
marginRight: 10
},
itemText: {
fontSize: 15,
margin: 5,
marginLeft: 20,
paddingTop:5,
paddingBottom:5
},
descriptionContainer: {
backgroundColor: '#F5FCFF',
marginTop: 8
},
infoText: {
textAlign: 'center'
},
titleText: {
fontSize: 18,
fontWeight: '500',
marginBottom: 10,
marginTop: 10,
textAlign: 'center'
},
directorText: {
color: 'grey',
fontSize: 12,
marginBottom: 10,
textAlign: 'center'
},
openingText: {
textAlign: 'center'
}
});
AppRegistry.registerComponent('SearchHeader', () => SearchHeader);
You need to pass the navigation prop down. Try this:
renderHeader = () => {
return (<SearchHeader navigation={this.props.navigation} />);
};
You need to wrap your component with withNavigation(Component)
Example: AppRegistry.registerComponent('SearchHeader', () => withNavigation(SearchHeader));
The point of withNavigation was so that you wouldn't need to pass navigation as a prop. Especially useful when you're passing through multiple children.

Categories

Resources