React Native List with Map Method
What I want to achieve, I want when click item then a new Item (I preferer add a new custom View) is added below the Selected item.
CodePudding user response:
There are some points to consider and I'll list them here, before providing an idea of a solution:
- React Native provides performance-optimized components that handle list rendering named
<FlatList />
/<SectionList />
. Use those components instead of.map()
for rendering component lists- You'll need to create an internal state for your list to be changed
- You need to provide a
key
prop when rendering a list of components using.map()
or other Array methodsWith minimal changes to your provided code, you can create a state to store the list and when the item is pressed you can insert a new item inside this list:
import React, { useState } from "react"; import { Text, View, StyleSheet, ScrollView, TouchableOpacity } from 'react-native'; const people = [/* your list */]; export default function App() { const [peopleList, setPeopleList] = useState(people) const [selectedId, setSelectedId] = useState(null); return ( <View style={styles.container}> <ScrollView> <View> {list.map((person, index) => { return ( <TouchableOpacity onPress={() => { setSelectedId(person.id) const newPerson = {...person}; // The new item setPeopleList((prevList) => [...prevList.slice(0,index 1), newPerson, ...prevList.slice(index 1)]) }} style={{ padding:20, backgroundColor: backgroundColor, marginBottom:20, }} > <Text>{person.name}</Text> </TouchableOpacity> ); })} </View> </ScrollView> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, padding:20 } });
Sandbox with working code: https://snack.expo.dev/5rvTbrEvO
CodePudding user response:
Since you are changing the background of the selected item, it is necessary that you update the ID's of every item in the list, for otherwise inserting elements will break this functionality. Furthermore, you need to add a state for for otherwise you cannot trigger a UI change
You could implement the desired behaviour as follows.
const [selectedId, setSelectedId] = useState(null); const [data, setData] = React.useState(persons) function handleOnPress(idx) { setSelectedId(idx) const first = data.slice(0, idx 1); const second = data.slice(idx 1).map(p => ({...p, id: Number(p.id) 1})); setData([...first, {id: idx 2, name: "Whatever new iten"}, ...second]) } return ( <View style={styles.container}> <ScrollView> <View> {data.map((person, index) => { const backgroundColor = index === selectedId ? "#6e3b6e" : "#f9c2ff"; return ( <TouchableOpacity onPress={() => handleOnPress(index)} style={{ padding:20, backgroundColor: backgroundColor, marginBottom:20, }} > <Text>{person.name}</Text> </TouchableOpacity> ); })} </View> </ScrollView> </View> );
Use
slice
in order to split the array into two parts. Usemap
for updating theid
attribute of the elements in the second array. Finally, combine both parts but insert a new element between them.