Reactjs assigning key prop to array rendered components - javascript

I am rendering some components using array map function, and I'm getting "Each child in an array or iterator should have a unique "key" prop." warning. I know that I do have to assign key props to the array rendered components.
My question is, do I have to just assign key to the most outer component (this case View) that is inside the map function, or do I have to assign key to every element inside the outer most component view?
If latter is the case, then assigning key to every component is a little inefficient I think? Is there any way to solve this problem? Thank you
this.state.Store.City.map((item) => {
return <View>
<TouchableOpacity onPress={() => this.onQueryInputChange(item)}>
<Text style={{ fontSize: 20, paddingVertical: 10 }}>
{item.fullName}
</Text>
</TouchableOpacity>
</View>
})

If you don't have an id in item, you can use the item array index if the list will not be reordered or reorganized :
this.state.Store.City.map((item, index) => {
return (
<View key={index}>
<TouchableOpacity onPress={() => this.onQueryInputChange(item)}>
<Text style={{ fontSize: 20, paddingVertical: 10 }}>
{item.fullName}
</Text>
</TouchableOpacity>
</View>
);
})
Only the outermost component needs a key to keep track of each item.

You should assign a key to the most outter component (here it would be View component)
here is the documentation
if item has an ìd property you could write
this.state.Store.City.map((item) => {
return (
<View key={item.id}>
<TouchableOpacity onPress={() => this.onQueryInputChange(item)}>
<Text style={{ fontSize: 20, paddingVertical: 10 }}>
{item.fullName}
</Text>
</TouchableOpacity>
</View>
);
})

Related

Get the key value when i click the respective TouchableOpacity from mapping an array

Im new to react native and im doing an internship but noone can really help me and i've been stuck with this for a while, my question is, im mapping an array that will basicly list news from an api each in a rectangle with title, subject and date. Everything is working but i wanted to click a rectangle for example so it shows more of that specific new but i dont know if there is any way i can store the key value in a variable so i can get the right coordinates of the array
{this.state.noticias.map((noticias, i) => (
(this.state.noticias[i][0] && this.state.noticias[i][1] && this.state.noticias[i][2]) == "" ?
<View key={i}></View> :
<TouchableOpacity style={styles.noticiaContainer} key={i}
onPress={this.mostrarNoticia.bind(this)} >
<View style={{ borderBottomWidth: 1, borderColor: '#0e62a5', }}>
<Text style={styles.tituloNoticia}>{noticias[0]}</Text>
</View>
<Text style={styles.assuntoNoticia}>{noticias[1]}</Text>
<Text style={styles.dataNoticia}>{noticias[2]}</Text>
</TouchableOpacity>
))}
The second argument to bind is the set of arguments to pass into the new function, so in your code where you're mapping each of your 'noticias', you're creating a new function with bind, and passing in the current 'this' value as the first parameter, but not passing in any variables.
Observe the amendment I have made to your code below, I have passed in both the 'noticias' and 'i' values as the 2nd & 3rd parameters to the bind function call.
{this.state.noticias.map((noticias, i) => (
(this.state.noticias[i][0] && this.state.noticias[i][1] && this.state.noticias[i][2]) == "" ?
<View key={i}></View> :
<TouchableOpacity
style={styles.noticiaContainer}
key={i}
onPress={this.mostrarNoticia.bind(this, noticias, i)} >
<View style={{ borderBottomWidth: 1, borderColor: '#0e62a5', }}>
<Text style={styles.tituloNoticia}>{noticias[0]}</Text>
</View>
<Text style={styles.assuntoNoticia}>{noticias[1]}</Text>
<Text style={styles.dataNoticia}>{noticias[2]}</Text>
</TouchableOpacity>
))}
Taking the above modification I've stubbed out an example function signature for 'mostrarNoticia', along with the fix for bind should look something like below.
import React from "react";
class YourComponent extends React.Component {
mostrarNoticia (noticias, index) {
// Given you passed the values into the bind function,
// they will be accessible here.
console.log("noticias", noticias);
console.log("index", index);
}
render () {
return (
<>
{this.state.noticias.map((noticias, i) => (
(this.state.noticias[i][0] && this.state.noticias[i][1] && this.state.noticias[i][2]) == "" ?
<View key={i}></View> :
<TouchableOpacity
style={styles.noticiaContainer}
key={i}
onPress={this.mostrarNoticia.bind(this, noticias, i)} >
<View style={{ borderBottomWidth: 1, borderColor: '#0e62a5', }}>
<Text style={styles.tituloNoticia}>{noticias[0]}</Text>
</View>
<Text style={styles.assuntoNoticia}>{noticias[1]}</Text>
<Text style={styles.dataNoticia}>{noticias[2]}</Text>
</TouchableOpacity>
))}
</>
);
}
}
Basically, pass the variables into the function using the bind function you're already using.

Styling array mapped objects in React Native

return arr.map((entry, index) =>
<View style={ this.state.interests.includes(entry) ? styles.optionSelected : styles.option}>
<TouchableOpacity onPress={() => this.addToInt(entry)}>
<Text style={{ color: "#22305D", paddingVertical: 15, paddingHorizontal: 25, fontSize: 18 }} key={entry}>{`${entry}`}</Text>
</TouchableOpacity>
</View>
)
I currently have this code to traverse my array and display all the values, but I want a way to change the styling of an individual object when pressed. The way I have it now, onPress adds that unique value to the array interests (100% sure this works), but the conditional styling isn't working. Is there a different way of handling this? I am trying to avoid setting a state for option1, option2, etc.. Thanks!

is there way to return Text and View together ? because it doesn't work for me

This is my example of return jsx elements inside the loadingMessage.
return (
<AzureLoginView
azureInstance={this.azureInstance}
loadingMessage={
<Text style={{ fontSize: 20, fontWeight: "bold" }}>loding data</Text>
Here it doesn't let me put my view inside the loadingMessage as listed below and I don't understand why.
<View style={styles.appBottomMainContainer}>
<View style={styles.appBottomView}>
<Text>{'\u00A9'}Developed by Mobile Team</Text>
</View>
</View>
}
onSuccess={this._onLoginSuccess}
/>)
As per the docs it states AzureLoginView loadingMessage should be a string rather than a JSX component. So try instead with that.
But in future , for any other components , yes you can return JSX components like FlatList uses it, Like thr one in renderItem :
<FlatList
data={this.props.tripsReducer.trips}
renderItem={({item, index}) => {
return (<View><Text>{item}</Text></View>);
}}
/>

React-Native How to change state value for each item?

I have a 'touchableOpacity' where each time its pressed it shows the selected value, but when a value is selected every item gets that value.
I need to do it this way:
item 1 -> selectedValue3
item 2 -> selectedValue1...
{ this.state.proyectosConTodo.map((item,index)=>{ return (
<View style={{paddingBottom:12}}>
<Grid>
<Col>
<View style={{height:40,justifyContent: 'center'}}>
<Text numberOfLines={1} allowFontScaling={false} style={{color: '#45526e',fontFamily: 'Roboto-Regular',fontSize:15, alignSelf: 'flex-start'}}>{item.proyecto.titulo}</Text>
</View>
</Col>
<Col>
<TouchableOpacity style={{ height:40,borderWidth:1, borderRadius:4, borderColor: '#e0e4eb', justifyContent: 'center',backgroundColor: '#f3f4f6'}} onPress={()=>{ this.setAgentesReasignarEnviar(item,index) }}>
<Text allowFontScaling={false} style={{color: '#45526e',fontFamily: 'Roboto-Medium',fontSize:15, marginLeft:10,marginRight:10}}>{this.state.txt_agenteProyecto}</Text>
<Icon style={{position: 'absolute',top:13,right:10}} name={ 'chevron-down'} size={10} color={ '#45526e'}/>
</TouchableOpacity>
</Col>
</Grid>
</View>
) }) }
From your snippet it seems that your structure is that one screen with a FlatList or something similar that renders multiples of your TouchableOpacity components. The problem is that every time a single TouchableOpacity is clicked it changes the state of the screen(not just itself) causing all touchable opacities to have that value.
One possible solution is the create another component which renders your list item and has its own state. The item used to render it can be passed as a prop and then calling setState inside that component will not affect the other list items.
I think this is what you need:
setAgentesReasignarEnviar(item, index) {
const result = this.state.proyectosConTodo.map(() => return item);
this.setState({
proyectosConTodo: result
});
}
For more detail, check this out: How to replace all undefined values in an array with "-" ?

Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of 'search'

The search is perfect and it's all looks fine, but gets this warning.
I get this warning when I press any key to start the search method.
"Song_ID", "Song_Name" and "Image" are of the variable names from the SQL Database.
- I looked on other question as this, but it didn't help me at all.
This is the code where the error is :
return (
<View>
<ScrollView>
{musicList.map(songObj => {
return (
<View style={styles.resultsContainer}> /// Its written that the erorr in this line
<TouchableOpacity onPress={this.GetListViewItem.bind(this, songObj.Song_Name)}>
<Text style={{ fontSize: 16 }} key={songObj.Song_ID}>
{songObj.Song_Name}</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
I don't understand where to put the key and/or what does it mean, I tried so many times but it didn't went well.
If more details is needed please tell me and I'll insert the right code.
You should add the key onto the outermost component inside the map. In your case, this is the View. Try this:
return (
<View>
<ScrollView>
{musicList.map(songObj => {
return (
<View style={styles.resultsContainer} key={songObj.Song_ID}>
<TouchableOpacity onPress={this.GetListViewItem.bind(this, songObj.Song_Name)}>
<Text style={{ fontSize: 16 }}>
{songObj.Song_Name}</Text>
<Image source={{ uri: songObj.Image }} style={styles.img} />
</TouchableOpacity>
</View>
);
})}
</ScrollView>
</View>
);
}
Adding the key prop lets react optimize rendering which is why it recommends you add it. Read the docs for more info.

Categories

Resources