How to concatenate JSX components in React Native - react-native

For example, I wanna show a list of names. So I wanted to do something like this:
var returnValue;
for (eachName of _names) {
returnValue += (
<TouchableHighlight
onPress={() => this._onPressButton}>
<Text>
{eachName}
</Text>
</TouchableHighlight>);
}
return returnValue;
However, that is not valid. Which brings me to my question: How do I concatenate a dynamic amount of JSX components in React Native.

Figures I figure it out soon as I ask stackoverflow. The code needs to be put into an array:
var returnValue = [];
for (var i = 0; i < _names.length; i++) {
returnValue.push(
<TouchableHighlight onPress={() => this._onPressButton}>
<Text>
{_names[i]}
</Text>
</TouchableHighlight>);
}
return returnValue;
There is also more information here: http://facebook.github.io/react/docs/multiple-components.html#dynamic-children

Maybe a more elegant way:
return <View>
{_names.map((eachName) => {
return (
<TouchableHighlight onPress={() => this._onPressButton}>
<Text>
{eachName}
</Text>
</TouchableHighlight>
);
})}
</View>

let returnValue = _names.map(eachName =>
<TouchableHighlight
onPress={() => this._onPressButton}>
<Text>
{eachName}
</Text>
</TouchableHighlight>);
return returnValue;

Related

How to use hooks as image's source in react native?

Im making this menu that when the user clicks at an option, it changes the background image, but i cant use the hook that i created as a parameter to the source of the image. Can someone find where im wrong and how to fix it?
Heres the part of my code referents to the menu and the hooks:
export function Home(){
let imagens = {
vovo: '../assets/vovoJuju.png',
mc: '../assets/mcJuju.png',
pato: '../assets/patoJuju.png',
}
const navigation = useNavigation<any>();
const [showBottomSheet, setShowBottomSheet] = React.useState(false);
const [param, setParam] = useState(1);
const [skin, setSkin] = useState('vovo')
const hide = () => {
setShowBottomSheet(false)
}
function handleAbout(){
navigation.navigate('About');
}
useEffect(() => {
if(param==1){
setSkin('vovo');
}
else if(param==2){
setSkin('mc');
}
else if(param==3){
setSkin('pato');
}
})
return(
<SafeAreaView style={styles.container}>
<TouchableOpacity onPress={handleAbout}>
<Counter />
</TouchableOpacity>
<TouchableOpacity onPress={() => {
setShowBottomSheet(true)
}}
>
<Image source={skin} style={styles.imgvj}/>
</TouchableOpacity>
<BottomSheet show={showBottomSheet} height={290} onOuterClick={hide}>
<Pressable onPress={hide} style={styles.bottomSheetContent}>
<Image source={barrinhaLoja} style={styles.barra}/>
</Pressable>
<View style={styles.conteudoLoja}>
<View style={styles.marginLeft48}>
<TouchableOpacity onPress={() => {
setParam(1);
}}>
<Image source={vovoJuju} style={styles.vovo}/>
<Text style={styles.legendasLoja}>Vovó Juju</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity onPress={() => {
setParam(2);
}}>
<Image source={mcJuju} style={styles.mc}/>
<Text style={styles.legendasLoja}>MC Juju</Text>
</TouchableOpacity>
</View>
<View>
<TouchableOpacity onPress={() => {
setParam(3);
}}>
<Image source={patoJuju} style={styles.pato}/>
<Text style={styles.legendasLoja}>Pato Juju</Text>
</TouchableOpacity>
</View>
</View>
</BottomSheet>
I created the "let imagens", "const param", "const skin" and the "useEffect trying" to make this function. I already tried using the source in different ways such as source={skin} and source={imagens[skin]} but it havent worked.
I'm not certain if this solves your problem, but here's how the first few lines of your component should look like without useEffect:
const imagens = {
vovo: '../assets/vovoJuju.png',
mc: '../assets/mcJuju.png',
pato: '../assets/patoJuju.png',
};
export function Home(){
const navigation = useNavigation<any>();
const [showBottomSheet, setShowBottomSheet] = React.useState(false);
const [param, setParam] = useState(1);
const hide = () => {
setShowBottomSheet(false)
}
function handleAbout(){
navigation.navigate('About');
}
let skin = 'vovo';
switch(param) {
case 1: skin = 'vovo'; break;
case 2: skin = 'mc'; break;
case 3: skin = 'pato'; break;
}
return /* the rest goes here */
}
To reference the actual image, you would use something like {imagens[skin]}.
I moved imagens outside of this function because it never changes, but it doesn't impact anything otherwise.

How do i display card with different items when key pass through navigator in react native

When pass the item to the next screen through navigator of radio.js the other screen attendence.js card shows all item details with same id in the card with multiple times when an C# API is called in attendancjs.
I want to show different items in the card when calling an API in attendance.js.
Radio.Js
onRadioBtnClick = () => {
data.map((item) =>
{
if(item.attendanceType==checked)
{
// if (index < item) {
// console.log(item)
// return item;
// }
// for(i=0;i<item.length;i++)
// {
// elements=item[i]
console.log({item})
// }
navigation.navigate('attendance',{item})
} }
);
enter image description here
Attendance.js
return (
<ScrollView>
{
// {`${post.attendanceTime}`+ `${post.attendanceType}`}
// console.log(item)
data.map(() => (
<View style={styles.view} >
<Card style={styles.cardWrapper} >
<View style={styles.card}>
<Text style={styles.title}>Key:{item.id} {'\n'}
Latitude:{item.latitude} {'\n'} Longitude:{item.longitude}{'\n'}
Attentance Time:{item.attendanceTime} {'\n'}
Attentance:{`${item.attendanceType}`}{item.attendanceType=="i"? (<Image style={styles.icon} source={require('../assests/checked.png')} /> ):(<Image style={styles.icon} source={require('../assests/delete.png')} />)}
{'\n'}
Employee Name: {item.userInfo.displayName}
</Text>
</View>
</Card>
</View>
))
You are passing object navigation.navigate('attendance',{item}) from Radio.js and in Attendance.js you are iterate over data array and display only item(which is one object) to length of data. So it will take length of data and display one item which is passed from Radio.js

how to use if condition in .map function?

Hi, I used if condition like below, but there is nothing rendering on the screen. By the way, there is 'MAVI' in leader array
renderall() {
return this.state.leader.map(alb => {
if(alb.Renk == 'MAVI') {
<View style={styles.container} key={counter = counter + 1}>
<Text style={[styles.textStyle, {marginLeft:'5%'}]}> {alb.Tescil_No} </Text>
<Text style={[styles.textStyle, {marginLeft:'6%'}]}> {alb.GumrukAdi} </Text>
<Text style={[styles.textStyle, { marginLeft:'5%'}]}> {alb.ACIKLAMA} </Text>
</View>
}
});
}
You're missing a return in your .map. Notice that inside the if statement I am returning the items being mapped.
renderall() {
return this.state.leader.map(alb => {
if(alb.Renk == 'MAVI') {
return (
<View style={styles.container} key={counter = counter + 1}>
<Text style={[styles.textStyle, {marginLeft:'5%'}]}> {alb.Tescil_No} </Text>
<Text style={[styles.textStyle, {marginLeft:'6%'}]}> {alb.GumrukAdi} </Text>
<Text style={[styles.textStyle, { marginLeft:'5%'}]}> {alb.ACIKLAMA} </Text>
</View>
);
}
});
}
This article explains in more detail how the .map function works
https://codeburst.io/learn-understand-javascripts-map-function-ffc059264783
Here is a very small example showing how to use the .map function. Notice the return statement.
let leaders = ['Tom','Jerry','Mike'];
let mappedLeaders = leaders.map((leader, index) => {
return `${leader} is number ${index}`; // notice that I am returning here
})
console.log(mappedLeaders)
Here is an example of using a .map with an if statement inside it. Notice we will get undefined for the first item in the mappedLeaders as we are not returning anything for the first item because Tom is excluded due to the fact that his name is too short.
let leaders = ['Tom','Jerry','Mike'];
let mappedLeaders = leaders.map((leader, index) => {
if (leader.length > 3) {
return `${leader} is number ${index}`; // notice that I am returning here
}
});
console.log(mappedLeaders)

Alternative text if data is not available

In React Native, how can I specify an alternative text to use if data is not available?
For example, in the following code, how would I specify to display "no skills, yet", if the skills array is empty?
<View>
<Text>
Skills
</Text>
<View>{
p.skills && p.skills.map( skill =>
<Text key={skill}>
{ skill }
</Text>
)
}</View>
</View>
You could either save the desired output in a variable before rendering:
let skillText = (<Text>{'no skills, yet'}</Text>);
if (p.skills && p.skills.length > 0) {
skillText = p.skills.map( skill =>
<Text key={skill}>
{ skill }
</Text>
);
}
...some more code...
<View>
<Text>
Skills
</Text>
<View>{ skillText }</View>
</View>
Or use a ternary directly in the jsx:
<View>
<Text>
Skills
</Text>
<View>{
(p.skills && p.skills.length > 0) ? p.skills.map( skill =>
<Text key={skill}>
{ skill }
</Text>
) : 'no skills, yet'
}</View>
</View>
First way (short one):
<View>
<Text>
Skills
</Text>
<View>
{
(p.skills && p.skills.length > 0) ? p.skills.map( skill =>
<Text key={skill}>
{ skill }
</Text>
) : (
<Text>no skills, yet</Text>
)
}
</View>
</View>
Second way: Extract the list rendering into a separate method
renderSkills = () => {
if (p.skills && p.skills.length > 0) {
return p.skills.map( skill =>
<Text key={skill}>
{ skill }
</Text>
)
} else {
return (
<Text>no skills, yet</Text>
)
}
}
render() {
return (
<View>
<Text>
Skills
</Text>
<View>
{this.renderSkills()}
</View>
</View>
)
}
PS: Please consider to use FlatList instead of rendering rows using Text (it helps a lot with performance)

How to get the style name and state name of a clicked element in React Native?

In the following, first example how do I check if the clickable element TouchableWithoutFeedback has the style named EntryBlock1?
render() {
return (
<TouchableWithoutFeedback style={styles.EntryBlock1} onPress={() => this.CheckIfHasStyles()}>
<View style={styles.redundantWrapperNumber1}>
<Text style={styles.redundantWrapperNumber2}>Click To Test For Style</Text>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback style={styles.EntryBlock2} onPress={() => this.CheckIfHasStyle()}>
<View style={styles.redundantWrapperNumber1}>
<Text style={styles.redundantWrapperNumber2}>Click To Test For Style</Text>
</View>
</TouchableWithoutFeedback>
); // end return
} // end render
In the 2nd example, how can I check if TouchableWithoutFeedback has the state name EntryBlock1 ?
constructor (props) {
super(props);
this.state = {
EntryBlock1: [styles.entryBlockButton, styles.entryBlockButtonMin],
EntryBlock2: [styles.entryBlockButton, styles.entryBlockButtonMax],
}
}
render() {
return (
<TouchableWithoutFeedback style={this.state.EntryBlock1} onPress={() => this.CheckIfHasStateName()}>
<View style={styles.redundantWrapperNumber1}>
<Text style={styles.redundantWrapperNumber2}>Click To Test For Style</Text>
</View>
</TouchableWithoutFeedback>
); // end return
What I've Tried
Different stuff along the lines of the following..
CheckIfHasStyles =()=> {
var object = this.state;
var stringifiedObject = JSON.stringify(object);
var slicedObject = stringifiedObject.slice(2, 13);
if (slicedObject === 'EntryBlock1') {
alert('success');
} else {
alert('failure');
}
}
.. which actually works for one very specific example, but not when I have multiple state names as this.state gets all of them in one object and not just the state of the element clicked.
Note: My question is solely about getting attributes and their values. It is to help me develop a style of toggling styles on elements but I am only looking for attribute stuff in these answers as I would like to use attributes, if possible, for more than just toggling in the future.
You can pass it as parameter to your function directly like this:
render() {
return (
<TouchableWithoutFeedback style={styles.EntryBlock1} onPress={() => this.CheckIfHasStyles('EntryBlock1')}>
<View style={styles.redundantWrapperNumber1}>
<Text style={styles.redundantWrapperNumber2}>Click To Test For Style</Text>
</View>
</TouchableWithoutFeedback>
<TouchableWithoutFeedback style={styles.EntryBlock2} onPress={() => this.CheckIfHasStyle('EntryBlock2')}>
<View style={styles.redundantWrapperNumber1}>
<Text style={styles.redundantWrapperNumber2}>Click To Test For Style</Text>
</View>
</TouchableWithoutFeedback>
);
}
and check if you are receiving any parameter in your function and do what you want
based on If-else condition