problems passing props to components - react-native

I'm struggling to pass props down into some components. I have an array of data that I'm using but cant access the props to be able to use the data.
I can seem to access the props in a components folder but for some reason I cant access the props from within the same folder.
Any ideas would be very much appreciated. Thanks in advance guys.
const homeOptions = [
{
name: "Create A Beast Workout",
body: "Quick Start Workout",
image: require("../assets/images/ChickSquat.jpg"),
id: "1",
},
{
name: "Beast Workout Diary",
body: "Create and manage your workout shedule",
image: require("../assets/images/DoubleBis.jpg"),
id: "2",
},
{
name: "Pre-Made Workouts",
body: "Use one of our pre-made workouts",
image: require("../assets/images/ChickA.jpg"),
id: "3",
},
{
name: "Statistics",
body: "Analyse your personal statistics",
image: require("../assets/images/WorkoutInProgress.jpg"),
id: "4",
},
{
name: "History",
body: "Keep track of your workout history",
image: require("../assets/images/ChickH.jpg"),
id: "5",
},
];
const HomeScreen = (props) => {
console.log(props);
return (
<View style={Styles.containerTop}>
<View>
<HomeScreenImage style={Styles.top} />
<View style={Styles.top}>
<BigButton title="Beast" />
</View>
</View>
<SafeAreaView style={Styles.flatListContainer}>
<FlatList
data={homeOptions}
renderItem={({ item }) => (
<TouchableOpacity
style={Styles.container}
onPress={() =>
props.navigation.navigate({
routeName: "StackNavigator",
params: {
cardId: props.info.id,
cardImage: props.info.image,
cardName: props.info.name,
cardBody: props.info.body,
},
})
}
>
//////below is where im having the problem accessing props /////////////////
<View style={Styles.cardContainer}>
<Image style={Styles.imageStyle} source={props.info.image} />
<View style={Styles.infoStyle}>
<Text style={Styles.titleStyle}>{props.info.name}</Text>
<Text style={Styles.bodyTextStyle}>{props.info.body}</Text>
</View>
</View>
</TouchableOpacity>
/>
</SafeAreaView>
</View>
);
};

Related

FlatList renderItem returning undefined

i have a flatList that renders a component with some props, but the renderItem returns me 'undefined'. I´m new to react-native and I cant´t find a solution. Thanks
edit:
Is it possible that the styles I used in 'posts.js' may affect the flatList render?
Feed.js:
export default function Feed() {
const Posts = [
{ id: 1, title: "eu", photoDesc: 'eu' },
{ id: 2, title: "me", photoDesc: 'me' }
]
console.log;
return (
<FlatList
keyExtractor={props => props.id}
data={Posts}
renderItem={({ item }) => <FeedPosts title={`${item.title}`} photoDesc={`${item.photoDesc}`} ></FeedPosts>}
>
</FlatList>
);
}
Posts.js:
export default function FeedPosts(props) {
return (
<Container>
<Header>
<TouchableOpacity>
<FontAwesome5 name='bell' size={40} style={{ marginLeft: 10 }}></FontAwesome5>
</TouchableOpacity>
<TouchableOpacity>
<Ionicons name='add-circle' size={40} style={{ marginRight: 5 }}></Ionicons>
</TouchableOpacity>
</Header>
<Body>
<Time>15/12/2021 as 17:42pm</Time>
<User>
<Icon source={require('../../assets/vibe.jpg')}></Icon>
<Description>{props.title}</Description>
</User>
<Content>
<PetPhoto source={props.postImg}></PetPhoto>
</Content>
<ContentDesc >
<PhotoDesc> {props.photoDesc}</PhotoDesc>
</ContentDesc>
<Bottom>
<Comment title="Comment" placeholder="Escrever Comentário"></Comment>
</Bottom>
<Buttons></Buttons>
</Body>
</Container>
);
}
Your variable Posts contains an array of React components. Instead, it should contain an array of data that you transform into components.
So your Posts should look more like this:
const Posts = [
{title: "My title", photoDesc: "Desc"},
{title: "My title2", photoDesc: "Desc2"},
{title: "My title3", photoDesc: "Desc3"}
]
Here's an example (straight from the React Native documentation) of how this works in context:
const DATA = [
{
id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
title: 'First Item',
},
{
id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
title: 'Second Item',
},
{
id: '58694a0f-3da1-471f-bd96-145571e29d72',
title: 'Third Item',
},
];
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const renderItem = ({ item }) => (
<Item title={item.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
</SafeAreaView>
);
}
(https://reactnative.dev/docs/flatlist)
You can see in the above example that DATA is an array of objects, which gets transformed with the function renderItem into components. Very similar to your use case.

To call props from an const object in react native/expo

I'm trying to figure out how to use const objects to create 3 categories in my trivia game. I'm defining each one of them like this:
const questions = [
{
question: "Qual o tipo de arquitetura utilizada na Igreja da Madre de Deus?",
answers: [
{ id: "1", text: "Colonial" },
{ id: "2", text: "Maneirista" },
{ id: "3", text: "Gótico" },
{ id: "4", text: "Barroco", correct: true }
]
},
{
question: "No século XIX, o pintor que pintou os painéis da igreja foi:",
answers: [
{ id: "1", text: "Sebastião Canuto da Silva Tavares", correct: true },
{ id: "2", text: "Frans Janszoon Post" },
{ id: "3", text: "Oscar Pereira da Silva" },
{ id: "4", text: "João de Deus Sepúlveda" }
],
quiz_answer: "Esse é o cara!"
}
]
export default questions;
There is a file called IndexQuiz, where I'm calling them through a menu of categories (inside TouchableOpacity):
export default ({ navigation }) => (
<ScrollView>
<SafeAreaView style={{alignItems: "center", flexDirection: "column"}}>
<TouchableOpacity onPress={() =>
navigation.navigate("Quiz", {
title: "Arquitetura",
questions: arquitetura,
color: "rgb(32, 53, 70)"
})}
style={DesafiosStyles.cardContainer}>
</TouchableOpacity>
<TouchableOpacity onPress={() =>
navigation.navigate("Quiz", {
title: "Curiosidades",
questions: curiosidades,
color: "rgb(32, 53, 70)"
})}
style={DesafiosStyles.cardContainer}>
</TouchableOpacity>
<TouchableOpacity onPress={() =>
navigation.navigate("Quiz", {
title: "História",
questions: historia,
color: "rgb(32, 53, 70)"
})}
style={DesafiosStyles.cardContainer}>
</TouchableOpacity>
</SafeAreaView>
</ScrollView>
);
But when it comes to the Quiz file, inside render I have this:
render() {
const questions = this.props.route.params.questions.length;
const question = questions[this.state.activeQuestionIndex];
//console.log(question);
return (
<View
style={[
styles.container,
{ backgroundColor: this.props.route.params.color }
]}
>
<StatusBar barStyle="light-content" />
<SafeAreaView style={styles.safearea}>
<View>
<Text style={styles.text}>{question.question}</Text>
<ButtonContainer>
{answers.map(answer => (
<Button
key={answer.id}
text={answer.text}
onPress={() => this.answer(answer.correct)}
/>
))}
</ButtonContainer>
</View>
<Text style={styles.text}>
{`${this.state.correctCount}/${this.state.totalCount}`}
</Text>
</SafeAreaView>
<Alert
correct={this.state.answerCorrect}
visible={this.state.answered}
/>
</View>
);
}
Every time I try to call any of these categories, I got the "undefined is not an object" exception. I've tried to import the files and the "questions" const itself, but it didn't work. As simple as that must be, I'm stuck in this (yep, I'm kinda slow and basically a newbie with react native lol):
<Text style={styles.text}>{question.question}</Text>
<ButtonContainer>
{answers.map(answer => (
<Button
key={answer.id}
text={answer.text}
onPress={() => this.answer(answer.correct)}
/>
))}
</ButtonContainer>
Without this code, it shows the counter: "this.state.correctCount}/${this.state.totalCount", but that's all. How can I call these questions and answers properly?
I think the problem is that you try to get questions from length property, not from questions object itself:
const questions = this.props.route.params.questions.length;
const question = questions[this.state.activeQuestionIndex];

Error with renderItem in React-native Flatlist

I'm trying to set up a flatlist to test it on a screen in React-native.
When I launch the emulator I'm getting this error : "Can't find variable renderItem" but I don't really know what's wrong with my code. It seemed that I had every element.
Is there someone that can help me ? Thanks a lot for any explanations or answer you can give to help.
import React, { Component } from "react";
import { Header } from "react-native-elements";
import {
FlatList,
SafeAreaView,
StatusBar,
StyleSheet,
Text,
ImageBackground,
View,
ScrollView,
Image,
TouchableOpacity
} from "react-native";
import i18n from "../../src/i18n";
import styles from "../../assets/Styles/Styles";
const DATA = [
{
id: "bd7acbea-c1b1-46c2-aed5-1",
title: "Test 1",
},
{
id: "3ac68afc-c605-48d3-a4f8-2",
title: "Test 2",
},
{
id: "58694a0f-3da1-471f-bd96-3",
title: "Test 3",
},
{
id: "58694a0f-3da1-471f-bd96-4",
title: "Test 4",
},
{
id: "58694a0f-3da1-471f-bd96-5",
title: "Test 5",
},
{
id: "58694a0f-3da1-471f-bd96-6",
title: "Test 6",
},
{
id: "58694a0f-3da1-471f-bd96-7",
title: "Test 7",
},
{
id: "58694a0f-3da1-471f-bd96-8",
title: "Test 8",
},
{
id: "58694a0f-3da1-471f-bd96-9",
title: "Test 9",
},
];
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.flightsListitem, style]}>
<Text style={styles.h3}>{item.title}</Text>
</TouchableOpacity>
);
export default class FlightsList extends Component {
constructor(props) {
super(props);
this.state = {
selectedId: '',
setSelectedId:''
}
};
renderItem = ({ item }) => {
const backgroundColor = item.id === selectedId ? "transparent" : "fff";
return (
<Item
item={item}
onPress={() => setSelectedId(item.id)}
style={{ backgroundColor }}
/>
);
};
render() {
return (
<ImageBackground
source={require("../../assets/images/background.jpg")}
style={styles.backgroundImage}
>
<Header
backgroundImage={require("../../assets/images/bg-header.png")}
backgroundImageStyle={{
resizeMode: "stretch",
}}
centerComponent={{
text: i18n.t("mytrips.title"),
style: styles.headerComponentStyle,
}}
containerStyle={[styles.headerContainerStyle, { marginBottom: 0 }]}
statusBarProps={{ barStyle: "light-content" }}
/>
<ScrollView style={styles.containerScrollNoMargins}>
<SafeAreaView style={styles.container}>
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
/>
<TouchableOpacity
style={styles.touchable2}
onPress={() => this.props.navigation.goBack()}
>
<View style={styles.view2}>
<Text style={styles.textimg2}>
{i18n.t("tripsform.action.back")}
</Text>
</View>
<Image
source={require("../../assets/images/btn-background.png")}
style={styles.tripsimg2}
/>
</TouchableOpacity>
</SafeAreaView>
<Text>{"\n"}</Text>
</ScrollView>
</ImageBackground>
);
};
}
change
renderItem={renderItem}
to
renderItem={this.renderItem}
You must use renderItem={this.renderItem}
Because your renderItem function is not a variable or inner function of your render function. So, you must use this when you're trying to call another function of your class.

FlatList item to image in React Native

I'm trying to loop across a JSON and for each item load an image but I get a syntax error.
const WizardContainer = props => {
ImagePathItems = [
{ path: '../../resources/svg/wizard-r.png', txtValue: "1" },
{ path: '../../resources/svg/wizard-c.png', txtValue: "2" },
{ path: '../../resources/svg/wizard-s.png', txtValue: "3" },
{ path: '../../resources/svg/wizard-d.png', txtValue: "4" }];
return (
<View style={styles.a}>
<View style={styles.b}>
<View style={styles.c}>
<FlatList
horizontal
data={ImagePathItems}
renderItem={({ item }) =>
<Image
style={styles.tinyLogo}
//source={require('../../resources/svg/wizard-d.png')}
source={require({ item.path })} //SYNTAX ERROR
/>
}
keyExtractor={item => item.txtValue}
/>
</View>
</View>
</View>
);
};
export default WizardContainer;
If I discomment the previous line load the image fine
Change ImagePathItems array and Image source as well like this
const WizardContainer = props => {
ImagePathItems = [
{ path: require('../../resources/svg/wizard-r.png'), txtValue: "1" },
{ path: require('../../resources/svg/wizard-c.png'), txtValue: "2" },
{ path: require('../../resources/svg/wizard-s.png'), txtValue: "3" },
{ path: require('../../resources/svg/wizard-d.png'), txtValue: "4" }];
return (
<View style={styles.a}>
<View style={styles.b}>
<View style={styles.c}>
<FlatList
horizontal
data={ImagePathItems}
renderItem={({ item }) =>
<Image
style={styles.tinyLogo}
source={item.path}
/>
}
keyExtractor={item => item.txtValue}
/>
</View>
</View>
</View>
);
};
export default WizardContainer;
Can you try putting require in the data object:
{path: require('../../resources/svg/wizard-r.png'), txtValue: 1}
And then in your code, you can just reference as
<Image source={(item.path)} />
Does that work?
You cannot use require with variables because jsbundler is running in build-time, it can't figure out which modules to bundle when the name is a dynamic variable.
So if you really want to use variable to import path with require you can use a syntax like this. Adding partial statiic string to require can make it work.
var restOfThePath = 'svg/wizard-r.png'
require('../../resources/' + restOfThePath)
Or you can just require them in an object then use the object in your code.
Also using { inside your require is the reason why you have a syntax error. If you remove it then error will go away.
.
.
const WizardContainer = props => {
ImagePathItems = [
{ path: require('../../resources/svg/wizard-r.png'), txtValue: "1" },
{ path: ('../../resources/svg/wizard-c.png'), txtValue: "2" },
{ path: ('../../resources/svg/wizard-s.png'), txtValue: "3" },
{ path: ('../../resources/svg/wizard-d.png'), txtValue: "4" }];
return (
<View style={styles.a}>
<View style={styles.b}>
<View style={styles.c}>
<FlatList
horizontal
data={ImagePathItems}
renderItem={({item}) =>
<Image
style={styles.tinyLogo}
source={item.path}
/>
}
keyExtractor={item => item.txtValue}
/>
</View>
</View>
</View>
);
};
export default WizardContainer;

Breakline after a item of an array reactnative

I have item that are in array. I want to change the line after setting the first item and so on. I am getting the values in a row. But I want it in column. I am getting value as:
015245088 9823178404 9851108404
But I want value as:
015245088
9823178404
9823178404
I have implemented as follows:
this.state = {
contact: [
{
id: 0,
name: '015245088'
},
{
id: 1,
name: '9823178404'
},
{
id: 2,
name: '9851108404'
}
]
}
<CardSection>
<FontAwesomeIcon style={styles.contentStyle} icon={faPhone} />
{
this.state.contact.map((item, index) => (
<TouchableOpacity
key={item.id}
style={styles.opacityStyle}
onPress={()=>Linking.openURL(`tel:${item.name}`)}>
<Text style={styles.contactStyle}>{item.name} </Text>
</TouchableOpacity>
))
}
</CardSection>
this.state = {
contact: [
{
id: 0,
name: '015245088'
},
{
id: 1,
name: '9823178404'
},
{
id: 2,
name: '9851108404'
}
]
}
<CardSection>
<FontAwesomeIcon style={styles.contentStyle} icon={faPhone} />
<View style={{flexDirection:'column'}}>
{
this.state.contact.map((item, index) => (
<TouchableOpacity
key={item.id}
style={styles.opacityStyle}
onPress={()=>Linking.openURL(`tel:${item.name}`)}>
<Text style={styles.contactStyle}>{item.name} </Text>
</TouchableOpacity>
}
</View>
</CardSection>
You need to change the flexDirection to column.
So, Just add the following styles to styles.contentStyle. Or wrap your map function with a View and add the following styles to it.
flexDirection: 'column'
flex: 1