Basically i'm trying to work with a map in javascript. And when i'm using a button, i want to delete the actual object used by the map (not only a element, literally all the things on this part of map). And when it's done, i'm reading the next etc...
Right now i have a map, i'm reading all my objects, but i don't know how can i delete the actual Object Used.
Show() {
return this.state.loads.map((data) => {
return (
<View style={{ flexDirection: 'row' }}>
<Text key={data} style={styles.inputText}>{data.service}</Text>
<TouchableOpacity style={styles.buttonDel} onPress={() => this.delete(data.id)}>
<Icon reverse name='delete' type='material' color='#54a9eb' size='20'/>
</TouchableOpacity>
</View>
)
})
}
If anyone have an idea, thanks.
splice in javascript removes your target element ... but you need to create a new copy of your loads array (in a new location in memory) ... cause react does only shallow comparison to determine when to re-render
deleteItem = (index) => {
const { loads } = this.state;
/** Important to make `setState` force refresh */
let newLoads = loads.slice();
newLoads = newLoads.splice(index, 1); /* Remove one element at index*/
this.setState({ loads: newLoads });
};
return this.state.loads.map((data, index) => {
return (
<View style={{ flexDirection: 'row' }}>
<Text key={data} style={styles.inputText}>{data.service}</Text>
<TouchableOpacity style={styles.buttonDel} onPress={() => this.deleteItem(indx)}>
<Icon reverse name='delete' type='material' color='#54a9eb' size='20'/>
</TouchableOpacity>
</View>
)
Related
I have a listing component in my react native map. in which I'm mapping the list of items in the component. How the problem is. I have been getting warnings that each child should have a unique key. Even though I have given them a unique key but still getting that warning.
here is the code.
<ScrollView horizontal>
{this.state.isLoading === true ? (
[...Array(7)].map((item, index) => <PremiumShimmer key={index} />)
) : this.state.isError === true ? (
<View>
<Text style={{ color: "black" }}>
Facing some issue to load data from server
</Text>
</View>
) : this.state.Data.length === 0 ? (
<Text style={{ color: "black" }}>No Data Founbd</Text>
) : (
this.state.Data.map((item) => (
this.ItemRenderer({item})
))
)}
</ScrollView>
ItemRenderer ({ item }) {
return (
<PremiumItemListComponent item={item} navigation={this.props.navigation} />
);
};
PremiumItemListComponent
<TouchableOpacity
style={styles.listBox}
onPress={() => this.props.navigation.navigate("Detail", { data: this.props.item })}
>
<ImageBackground style={styles.listImage} imageStyle={{ borderRadius: 26}} source={{uri:SERVER_URL.apiUrl+this.props.item.background}}>
<Text style={{color:"white",fontSize:13,paddingLeft:10,fontWeight: 'bold'}}>{this.props.item.name}</Text>
<View style={{ flexDirection: 'row', flexWrap: 'wrap',padding:10}}>
{
[...Array(5)].map((e, i) =>
// 3.688689 will be replaced by rating
// console.log(typeof i,typeof 4, i+1<=4)
<Ionicons name={i+1<=Number((3.688689).toFixed(0))?"star-sharp":"star-outline"} size={15} color="#FFE600" />
)
}
</View>
</ImageBackground>
</TouchableOpacity>
I have console logged item.ids and they are unique 23, 24, and 25.
if You need more code to help. You can ask. Thanks in Advance.
Your code looks right, i don't think the warning you are getting for key is from this specific component, but i would like to add a few things to make your life a little easier.
Never use Index as key. Index will change if your data changes which will eventually make the purpose of keys useless.
Wherever possible use FlatList Component instead of a map since you get a easy keyExtractor Prop and it increases your performance if the list is long
Example : -
<FlatList
data={DATA}
renderItem={renderItem}
keyExtractor={item => item.id}
/>
using the keyExtractor Prop you can pick out and convert a unique value from your data into a key and it automatically adds the key prop into rendered component wrapper.
I doubt this is possible but I'd like to hear your thoughts.
I am getting an array which the number of values are unknown.
And I am using a for loop to spread it in a state:
const { letters,number } = route.params
const [arr,setArr] = useState([])
useEffect(() => {
var eachArr = []
setArr([])
for (let i = 1; i < Number(number) + 1; i++) {
eachArr.push(i)
}
setArr(eachArr)
}, [])
Now I use the state to map through to render accordingly
return (
<View style={styles.container}>
<ScrollView>
{
arr.length > 0 && arr.map(num => (
<View style={styles.placeContainer} key={num}>
<View style={styles.place}>
<Text style={{ fontWeight:'bold',letterSpacing:1 }}>{num} {letters}</Text>
<Feather name="check-circle" size={24} color="grey" />
</View>
<View style={{ marginVertical:10 }}>
<Progress color={colors.purple} progress={1} width={null} borderWidth={0} />
</View>
<View style={styles.button}>
<Text style={{ color:colors.white,fontFamily:'viga' }}> this {letters}</Text>
</View>
<View style={{...styles.button,backgroundColor:colors.lightPurple}}>
<Text style={{ color:colors.white,fontFamily:'viga' }}> this {letters}</Text>
</View>
</View>
))
}
</ScrollView>
</View>
)
I now have a problem. I have two buttons on each of the mapped element/component as you can see above.
I need to listen for a click on one and deactivate the clicked button and then activate the other button.
The problem is that I do not know how to set/update a state based on the which button is clicked since the number of rows are unknown.
I know I can call a function:
const callFunc = (val) -> {
console.log(val)
}
And call the function when a respective button is clicked and pass the val or sth. While this solves some part of the issue, how do I then deactivate it and active the new button when I didn't set a state for it
I have a object which has an array inside it. Each array has multiple objects. So using the .map function I am looping over the array inside the object. Each array item has a click function where I toggle the item. Initial state of the array item is this
{
DisplayText: "Foresatte"
Selectable: true
UserRecipientToInclude: "IncludeGuardianRecipient"
}
When I do this
choice.Selected = false
and console logs the result the newly added item is not present in the object. Why is that?
Here is the code
{c.UserDropdownMenuChoices.map(choice => {
return ( <TouchableHighlight
{...testProperties(choice.DisplayText, true)}
style={{ opacity: !choice.Selectable ? 0.4 : 1 }}
onPress={() => {
this.selectChoice(c.UserDropdownMenuChoices, choice, c)
}}
underlayColor={'transparent'}
key={choice.DisplayText}
>
<View style={styles.choiceContainer}>
{
choice.selected ? (
//<MaterialCommunityIcons name={'checkbox-marked'} style={styles.checkboxClick} size={20} />
<Icon
type={'material-community'}
name={'checkbox-marked'}
iconStyle={styles.checkboxClick}
size={20}
/>
) : (
<Icon
type={'material-community'}
name={'checkbox-blank-outline'}
iconStyle={styles.checkboxDefault}
size={20}
/>
)
//DONE: <MaterialCommunityIcons name={'checkbox-blank-outline'} style={styles.checkboxDefault} size={20} />
}
<Text style={styles.displayText}>{choice.DisplayText}</Text>
</View>
</TouchableHighlight> )}
and my function is like this
selectChoice(choicesList, choice, contact) {
choice.selected = true
...
console.log(choice) // doesn't have the new property
}
This code is for a react native application
I have previously solved a similar issue by simply scoping out the select hook inside the .map without mapping the attribute onto the array itself.
So what I did was:
import MenuRow from "./menu_row"
...
const Rooms = allRooms.map((room, index) => {
return (
<MenuRow key={room.id} room={room}/>
)
})
Inside MenuRow.js
const MenuRow = (props) => {
let room = props.room
const [selected, setSelected] = useState(true) // Checked by default
return (
<TouchableOpacity onPress={() => {setSelected(!selected), applySelected(room.id, selected) }} style={s.checkrow}>
...
{selected ?
// SELECTED
<View style={s.checked}></View>
:
// NOT SELECTED
<View style={s.unchecked}></View>
}
</TouchableOpacity>
)
However you could also give this a try:
https://stackoverflow.com/a/44407980/4451733
I'm trying to map an array from state - but confused re the correct syntax - can anyone please advise where i'm going wrong:
This is what I have at the mo:
newsStorys = () => {
return (
{this.state.newsFeed.map((a) => {
<View style={ModalStyles.newsArticle}>
<Text style={ModalStyles.newsDate}>{a.date}</Text>
<Text style={ModalStyles.newsTitle}>{a.title}</Text>
<Text style={ModalStyles.newsDesc}>
{a.story}
</Text>
</View>
}
}
);
};
I'm not sure if that is the whole code of your component, but I can see three things.
If newsFeed is not initialized when component first render (let's say it is undefined yet), then newsFeed.map()will throw an exception.
You are not returning anything from map call. you should write something like this:
newsStorys = () => {
if (!this.state.newsFeed) return null;
return this.state.newsFeed.map((a) => ({ // <--- note the parentheses here, you don't have it
<View style={ModalStyles.newsArticle}>
<Text style={ModalStyles.newsDate}>{a.date}</Text>
<Text style={ModalStyles.newsTitle}>{a.title}</Text>
<Text style={ModalStyles.newsDesc}>
{a.story}
</Text>
</View>
});
);
};
If you want to avoid the parentheses, then you need to explicitly return something, like this:
this.state.newsFeed.map((a) => {
return (
<View style={ModalStyles.newsArticle}>
<Text style={ModalStyles.newsDate}>{a.date}</Text>
<Text style={ModalStyles.newsTitle}>{a.title}</Text>
<Text style={ModalStyles.newsDesc}>
{a.story}
</Text>
</View>
);
});
It is possible that you need an extra view to wrap the list of views returned by map.
Also you need to provide a unique key to each view, so React can keep track on them.
<View style={ModalStyles.newsArticle} key={'nome unique value'}>
...
</View>
Finally I think it would be better using a FlatList instead of map.
Cheers!
Had a play and a good dig around the web and found the syntax answer: (Thanks to Bruno for the Key and pointers).
newsStorys = () => {
return this.state.newsFeed.map((value, index) => {
return (
<View style={ModalStyles.newsArticle} key={index}>
<Text style={ModalStyles.newsDate}>{value.date}</Text>
<Text style={ModalStyles.newsTitle}>{value.title}</Text>
<Text style={ModalStyles.newsDesc}>{value.story}</Text>
</View>
);
});
};
Try this
newsStorys = () => (
this.state.newsFeed.map(({ date, story, title }, index) =>
<View key={`news-${index}`} style={ModalStyles.newsArticle}>
<Text style={ModalStyles.newsDate}>{date}</Text>
<Text style={ModalStyles.newsTitle}>{title}</Text>
<Text style={ModalStyles.newsDesc}>{story}</Text>
</View>
));
I currently have two buttons (No, Yes)( component imported from native-base package) that when pressed should update the state with either 0 or 1 respectively and also toggle between true or false to notify if this field has been filled (by default, neither of the two will be pressed, hence set to false).
I have a handleOnClick() function bound to the "No" button with a debugger to test if I actually do hit it, but once inside this function, I'm not sure how to grab any info for associated components (i.e. the "No" text within the Text component) so I can perform logic to check if "No" or "Yes" was pressed.
If this was done in pure React, I know I can access certain data attributes that I add to DOM elements or traverse the DOM, but I'm not sure how to do this in React Native or if I'm able to add custom props to a built in component that I can then access.
class Toggle extends Component {
constructor() {
super()
this.state = {
selectedOption: '',
isFilled: false
}
this.checkField = this.checkField.bind(this)
this.handleOnClick = this.handleOnClick.bind(this)
}
checkField() {
console.log(this)
// debugger
}
handleOnClick(ev) {
debugger
console.log("I was pressed")
}
render() {
const options = this.props.inputInfo.options //=> [0,1]
const optionLabels = this.props.inputInfo.options_labels_en //=>["No","Yes"]
return (
<View style={{flexDirection: 'row'}}>
<View style={styles.row} >
<Button light full onPress={this.handleOnClick}><Text>No</Text></Button>
</View>
<View style={styles.row} >
<Button success full><Text>Yes</Text></Button>
</View>
</View>
)
}
}
If you want to pass information into function, you can pass it when it is called. In your case, you can call your function from arrow function, like so:
<View style={{flexDirection: 'row'}}>
<View style={styles.row} >
<Button light full onPress={() => this.handleOnClick('No')}>
<Text>No</Text>
</Button>
</View>
<View style={styles.row} >
<Button success full><Text>Yes</Text></Button>
</View>
</View>
And in your function
handleOnClick(text) {
debugger
console.log(`${text} pressed`)
}
Have you tried:
render() {
const options = this.props.inputInfo.options //=> [0,1]
const optionLabels = this.props.inputInfo.options_labels_en //=>["No","Yes"]
return (
<View style={{flexDirection: 'row'}}>
<View style={styles.row} >
<Button light full onPress={() => this.handleOnClick('No')}><Text>No</Text></Button>
</View>
<View style={styles.row} >
<Button success full onPress={() => this.handleOnClick('Yes')}><Text>Yes</Text></Button>
</View>
</View>
)
}
and
handleOnClick(word) {
this.setState({ selectedOption: word, isFilled: true })
}