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.
Related
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);
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;
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 (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,
}
i have this model into react native that name LoginView.js
"use strict";
import React, { Component } from 'react';
import { AppRegistry,TouchableOpacity, Text ,Button,Image,TextInput,PropTypes,StyleSheet,View,NavigatorIOS,TouchableHighlight} from 'react-native';
class LoginView extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>
HYGEX
</Text>
<View>
<TextInput
placeholder="Username"
style={styles.formInput}
/>
<TextInput
placeholder="Password"
secureTextEntry={true}
style={styles.formInput1}
/>
<TouchableHighlight style={styles.button}
onPress={() => this.move()}>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
</View>
);
}
move() {
//here !!
}
}
var styles = StyleSheet.create({
container: {
padding: 30,
marginTop: 65,
alignItems: "stretch"
},
title: {
fontSize: 18,
marginBottom: 10
},
formInput: {
height: 36,
padding: 10,
marginRight: 5,
marginBottom: 5,
marginTop: 5,
flex: 1,
fontSize: 18,
borderWidth: 1,
borderColor: "#555555",
borderRadius: 8,
color: "#555555"
},
button: {
height: 36,
flex: 1,
backgroundColor: "#555555",
borderColor: "#555555",
borderWidth: 1,
borderRadius: 8,
marginTop: 10,
justifyContent: "center"
},
buttonText: {
fontSize: 18,
color: "#ffffff",
alignSelf: "center"
},
});
module.exports = LoginView;
in this module i have method called move, when click into touchable move must open this module that name test.js
import React, { Component } from 'react';
import { AppRegistry, Text } from 'react-native';
class HelloWorldApp extends Component {
render() {
return (
<Text>Hello world!</Text>
);
}
}
i need this method in project its very important for me , if any one can tell me how to do this please !!
Note : iam beginner into react-native :)
Edit
i tried this code
login.js
"use strict";
import React, { Component } from 'react';
import { AppRegistry,TouchableOpacity, Text ,Button,Image,TextInput,PropTypes,StyleSheet,View,NavigatorIOS,TouchableHighlight} from 'react-native';
class LoginView extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.title}>
HYGEX
</Text>
<View>
<TextInput
placeholder="Username"
style={styles.formInput}
/>
<TextInput
placeholder="Password"
secureTextEntry={true}
style={styles.formInput1}
/>
<TouchableHighlight style={styles.button}
onPress={() => this.OnBUttonPress()}>
<Text style={styles.buttonText}>Login</Text>
</TouchableHighlight>
</View>
</View>
);
}
OnBUttonPress = () => {
this.props.navigator.push({
id: 'test'
})
}
}
var styles = StyleSheet.create({
container: {
padding: 30,
marginTop: 65,
alignItems: "stretch"
},
title: {
fontSize: 18,
marginBottom: 10
},
formInput: {
height: 36,
padding: 10,
marginRight: 5,
marginBottom: 5,
marginTop: 5,
flex: 1,
fontSize: 18,
borderWidth: 1,
borderColor: "#555555",
borderRadius: 8,
color: "#555555"
},
button: {
height: 36,
flex: 1,
backgroundColor: "#555555",
borderColor: "#555555",
borderWidth: 1,
borderRadius: 8,
marginTop: 10,
justifyContent: "center"
},
buttonText: {
fontSize: 18,
color: "#ffffff",
alignSelf: "center"
},
});
module.exports = LoginView;
AppRegistry.registerComponent('AwesomeProject', () => LoginView);
and this test.js
import React, { Component } from 'react';
import {
View,
Text,
TouchableHighlight,
} from 'react-native';
export default class WelcomeScreen extends Component {
constructor(props) {
super(props);
this.state = {
text: '<Your welcome in Second Screen>',
textBack: '<Tap to Go Back to First Screen>'
}
}
OnBUttonPress = () => {
this.props.navigator.push({
id: 'WelcomeScreen'
})
}
render = () => {
return (
<View>
<Text>{this.state.text}</Text>
<TouchableHighlight onPress={this.OnBUttonPress}>
<Text>{this.state.textBack}</Text>
</TouchableHighlight>
</View>
);
}
}
i got this error
undefined is not an object (evaluating'_this.props.navigator.push)
i have created a solution for multiple screen. so please read my code and implement as your requirement hope it will help you. Link here:
Navigator sample
if get any problem please ask me.