Alert Delete: Unable to delete item from flat list - javascript

I created a flatlist and a float icon to delete a item from flat list but before it's get delete user will get Alert and on press yes it will b deleted everything is working but after pressing yes item didn't deleted. How can i delete it?
Here is my code
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
image: null,
};
deleteItem = (key) => {
Alert.alert("Delete", "Are You Sure?", [
{
text: "Yes",
onPress: this.setState({
post: this.state.post.filter((item) => item.key !== key),
}),
},
{ text: "no" },
]);
};
render(){return(
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={this.deleteItem}
style={styles.Delete}
>
<MaterialCommunityIcons name="delete" color="red" size={30} />
</TouchableOpacity>
Someone please help,.............................

You might need to pass the item or an index of the item to the function, but I'm not sure of the internals of the TouchableOpacity component. The following shows how to pass the item and its key to the deleteItem method:
deleteItem = (item) => {
Alert.alert("Delete", "Are You Sure?", [
{
text: "Yes",
onPress: () => this.setState({ // edited
post: this.state.post.filter((p) => p.key !== item.key),
}),
},
{ text: "no" },
]);
};
render(){
return(
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.deleteItem(item)}
style={styles.Delete}
>
<MaterialCommunityIcons name="delete" color="red" size={30} />
</TouchableOpacity>
</>
)}
/>
);
};

In the FlatList
You have to use the prop keyExtractor inside the FlatList. (By doing this you assign a key to every object inside the array)
You also have to pass in the key inside your “deleteItem()” function
Like I have done in the below codes
import React from 'react'
import {View, Text,StyleSheet, FlatList,TouchableOpacity,Alert} from 'react-native'
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
},
],
image: null,
};
}
deleteItem = (key) => {
Alert.alert("Delete", "Are You Sure?", [
{
text: "Yes",
onPress:()=> this.setState({
post: this.state.post.filter((item) => item.key !== key),
}),
},
{ text: "no",
onPress:()=>null },
]);
};
render(){return(
<View style={{flex:1}}>
<FlatList
data={this.state.post}
keyExtractor={(item)=> item.key}
renderItem={({ item }) => (
<TouchableOpacity
onPress={()=>{this.deleteItem(item.key)}}
>
<View>
<Text>`Click here to Delete this =${item.title}`</Text>
<MaterialCommunityIcons name="delete" color="red" size={30} />
</View>
</TouchableOpacity>
)}/>
</View>
)}
}

Related

undefined is not an object (evaluating '_this.el')

*I use the ref property in the flatlist component in react native, but I get an undefined is not an
object error. I looked at many places on
the internet but did not get a satisfactory answer. Please help me :)*
const DATA = [
{
id: 0,
title: "First Item",
},
{
id: 1,
title: "Second Item",
},
];
const [selectedId, setSelectedId] = useState(null);
**React.useEffect(() => {
this.el.scrollToIndex({ animated: true, index:selectedId});
}, []);**
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.item, style]}>
<Text style={styles.title}>{item.title}</Text>
</TouchableOpacity>
);
const renderItem = ({ item }) => {
const backgroundColor = item.id === selectedId ? "#6e3b6e" : "#f9c2ff";
return (
<Item
item={item}
onPress={() => setSelectedId(item.id)}
style={{ backgroundColor }}
/>
);
};
return (
<>
<FlatList
data={DATA}
horizontal={true}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
**ref={(el) => this.el = el}**strong text
/>
</>
)
}```
To use a ref, you need to use useRef (since you're on a function component). On function components you won't find yourself using this. When using useRef, you'll need to use .current to access the item itself. So, you can see I'm doing el.current.scrollToIndex
Also, you'll need to add selectedId as a dependency to your useEffect
export default function App() {
const DATA = [
{
id: 0,
title: "First Item",
},
{
id: 1,
title: "Second Item",
},
{
id: 2,
title: "Second Item",
},
{
id: 3,
title: "Second Item",
},
{
id: 4,
title: "Second Item",
},
{
id: 5,
title: "Second Item",
},
{
id: 6,
title: "Second Item",
},
];
const [selectedId, setSelectedId] = React.useState(null);
const el = React.useRef()
React.useEffect(() => {
el.current.scrollToIndex({ animated: true, index:selectedId});
}, [selectedId]);
const Item = ({ item, onPress, style }) => (
<TouchableOpacity onPress={onPress} style={[styles.item, style]}>
<Text style={styles.title}>{item.title}</Text>
</TouchableOpacity>
);
const renderItem = ({ item }) => {
const backgroundColor = item.id === selectedId ? "#6e3b6e" : "#f9c2ff";
return (
<Item
item={item}
onPress={() => setSelectedId(item.id)}
style={{ backgroundColor }}
/>
);
};
return (
<>
<FlatList
data={DATA}
horizontal={true}
renderItem={renderItem}
keyExtractor={(item) => item.id}
extraData={selectedId}
ref={el}
/>
</>
)
}

How to access and update a field in an array of objects in React?

I'm trying to fill in the 'ans' fields in an array of inputs, but when I type in one of the inputs, it overrides all other objects in the state. How do I update the 'ans' fields in the object array, when I type something in one of the inputs, in the correct way, without it overwriting the other objects in the array within the state?
My code:
import React, { useState } from "react";
import {
StyleSheet,
View,
Text,
KeyboardAvoidingView,
ScrollView,
TextInput,
Button,
} from "react-native";
export default function List({ navigation }) {
const [data, setData] = useState({
"creator": {
"creatorAuthor": "Alisson",
"user": "",
},
"customField": [
{
"ans": "",
"quests": "Quest 1",
},
{
"ans": "",
"quests": "Quest 2",
},
{
"ans": "",
"quests": "Quest 3",
},
],
"date": {
"dateCreator": "01/01/2021",
"dateUser": "",
},
"id": "-MQxtMmc_K7rDIgutcNC",
"title": "Google",
}
);
return (
<KeyboardAvoidingView style={{backgroundColor: 'white', flex: 1}} enabled>
<ScrollView contentContainerStyle={{ padding: 10 }}>
<View>
<Text>{data.title}</Text>
</View>
<View>
<Text>{ data.creator.creatorAuthor}</Text>
<TextInput
style={{marginBottom: 20}}
placeholderTextColor= '#808080'
value={data.creator.user}
onChangeText={value => setData({ ...data, creator: {...data.creator, user: value} })}
placeholder='Usuário'
multiline={true}
/>
</View>
<View>
<Text>{data.date.dateCreator}</Text>
<TextInput
style={{marginBottom: 20}}
placeholderTextColor= '#808080'
value={data.date.dateUser}
onChangeText={value => setData({ ...data, date: {...data.date, dateUser: value} })}
placeholder='Data das repostas'
/>
</View>
{
data.customField.map((q, id) => (
<View key={id}>
<Text>{q.quests}</Text>
<TextInput
style={{marginBottom: 20}}
placeholderTextColor= '#808080'
value={q.ans}
onChangeText={value => setData({ ...data, customField: [{...q, ans: value}] })}
placeholder='Resposta'
multiline={true}
/>
</View>
))
}
<Button
title='Salvar'
onPress={() => {}}
/>
</ScrollView>
</KeyboardAvoidingView>
);
}
This will only produce an array of one value:
onChangeText={value => setData({ ...data, customField: [{...q, ans: value}] })}
You have to copy over the original array and replace the value you want to update:
onChangeText={value => setData({ ...data, customField: [data.customField.filter(cf => cf.quests !== q), {...q, ans: value}] })}
I didn't test the syntax, but should be something like this.
I would recommend to split the data into multiple state fields as it will allow you simpler syntax and will be more obvious what you doing:
const [customField, setCustomField] = useState({ -your custom field data here-});
{
customField.map((q, id) => (
<View key={id}>
<Text>{q.quests}</Text>
<TextInput
style={{marginBottom: 20}}
placeholderTextColor= '#808080'
value={q.ans}
onChangeText={value => setCustomField([ customField.filter(cf => cf.quests !== q), {...q, ans: value}]}
placeholder='Resposta'
multiline={true}
/>
</View>
))
}

React native, Failed prop type: Invalid prop `source` supplied to `Image`

Failed prop type: Invalid prop source supplied to Image I'm getting that error while uploading image.
I used image picker to pick image and made it component but it's not picking up source below is my code of image picker
FormImage.js
class FormImage extends Component {
state = {
hasCameraPermission: null,
};
async componentDidMount() {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
this.setState({ hasCameraPermission: status === "granted" });
}
_pickImage = async () => {
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.Images,
allowsEditing: true,
aspect: [4, 3],
});
if (!result.cancelled) {
this.setState({ image: result.uri });
this.props.formikProps.setFieldValue("image", result.uri);
}
};
render() {
return (
<TouchableWithoutFeedback onPress={this._pickImage}>
<View style={styles.container}>
{!this.props.image && (
<MaterialCommunityIcons
color={colors.medium}
name="camera"
size={40}
/>
)}
{this.props.image && (
<Image style={styles.image} source={{ uri: this.props.image }} />
)}
</View>
</TouchableWithoutFeedback>
);
}
}
I don't know why it's showing that error i will share my formik code below
AddPost.js
const validationSchema = Yup.object({
title: Yup.string().required().min(5).max(15).label("Title"),
des: Yup.string().required().min(15).max(200).label("Description"),
image: Yup.mixed(),
});
class AddPost extends Component {
render() {
return (
<Formik
initialValues={{ title: "", des: "", image: null }}
onSubmit={(values, actions) => {
this.props.addPost(values);
console.log(values);
}}
validationSchema={validationSchema}
>
{(value) => (
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 100}
>
<FormImage formikProps={value} image={value.values.image} />
<Text style={styles.error}>
{value.touched.image && value.errors.image}
</Text>
<TextInput
placeholder="Title"
onChangeText={value.handleChange("title")}
style={styles.input}
value={value.values.title}
onBlur={value.handleBlur("title")}
/>
below is my home screen code
home.js
class Home extends Component {
state = {
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
};
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState((prevState) => {
return {
post: [...prevState.post, posts],
modal: false,
};
});
};
render() {
return (
<Screen style={styles.screen}>
<Modal visible={this.state.modal} animationType="slide">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalContainer}>
<AddPost addPost={this.addPost} />
</View>
</TouchableWithoutFeedback>
</Modal>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<Card
title={item.title}
subTitle={item.des}
image={item.image}
onPress={() => this.props.navigation.navigate("Details", item)}
/>
</>
can someone tell me whats going on why it's not picking the source :/

React Native, Change value From Child class

I made 2 screens 1st home screen and 2nd for edit screen. I want to update the values from edit screen but when I click save button it shows an error setState(...): takes an object of state variables to update or a function which returns an object of state variables and display a blank home screen. Can someone please tell me how to update value from the child class? Below is my code, please help
home.js
class Home extends Component {
state = {
modal: false,
editMode: false.
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
};
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState((prevState) => {
return {
post: [...prevState.post, posts],
modal: false,
};
});
};
onEdit = (data) => {
this.setState({ post: { title: data }, editMode: false });
};
render() {
if (this.state.editMode)
return <EditScreen item={item} onEdit={this.onEdit} />;
return (
<Screen style={styles.screen}>
<Modal visible={this.state.modal} animationType="slide">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalContainer}>
<AddPost addPost={this.addPost} />
</View>
</TouchableWithoutFeedback>
</Modal>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.setState({ editMode: true })}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<Text style={styles.title} numberOfLines={1}>
{item.title}
</Text>
<Text style={styles.subTitle} numberOfLines={2}>
{item.des}
</Text>
</View>
</Card>
</>
)}
/>
</Screen>
Edit.js
<KeyboardAvoidingView
behavior="position"
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 100}
>
<Image style={styles.image} source={item.item} />
<View style={styles.detailContainer}>
<AppTextInput value={item.title} />
<AppTextInput value={item.des} />
</View>
<AppButton
text="Save"
onPress={() => {
onEdit(this.state);
this.props.navigation.goBack("Home");
}}
/>
</KeyboardAvoidingView>
I'm also getting a warning
This can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/troubleshooting#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state for more details.
It looks as though ListDetails is not actually a child of Home. If it were you could pass the onEdit function down as props.
You should not pass it as navigation params because when you leave the Home page it will be unmounted and you won't be able to update the state.
One way to achieve what you want is to use the Context api to setup a store for your application state.
Check this out: https://reactjs.org/docs/context.html
Edit, without context:
You will need to move the ListDetails component inside the Home component as a child. You can keep a value in state to check if you are in edit mode. Something like this maybe:
class Home extends Component {
state = {
selectedItem: undefined,
modal: false,
post: [
{
key: "1",
title: "A Good Boi",
des: "He's a good boi and every one know it.",
image: require("../assets/dog.jpg"),
},
{
key: "2",
title: "John Cena",
des: "As you can see, You can't see me!",
image: require("../assets/cena.jpg"),
},
],
};
addPost = (posts) => {
posts.key = Math.random().toString();
this.setState((prevState) => {
return {
post: [...prevState.post, posts],
modal: false,
};
});
};
onEdit = (data) => {
this.setState({ post: { title: data }, editMode: false, selectedItem: undefined });
};
render() {
const { editMode, selectedItem } = this.state;
if (editMode && selectedItem) return <ListDetails item={selectedItem} onEdit={onEdit} />
return (
<Screen style={styles.screen}>
<Modal visible={this.state.modal} animationType="slide">
<TouchableWithoutFeedback onPress={Keyboard.dismiss}>
<View style={styles.modalContainer}>
<AddPost addPost={this.addPost} />
</View>
</TouchableWithoutFeedback>
</Modal>
<FlatList
data={this.state.post}
renderItem={({ item }) => (
<>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => this.setState({ editMode: true, selectedItem: item })}
style={styles.Edit}
>
<MaterialCommunityIcons
name="playlist-edit"
color="green"
size={35}
/>
</TouchableOpacity>
<Card>
<Image style={styles.image} source={item.image} />
<View style={styles.detailContainer}>
<Text style={styles.title} numberOfLines={1}>
{item.title}
</Text>
<Text style={styles.subTitle} numberOfLines={2}>
{item.des}
</Text>
</View>
</Card>
</>

React Native highlight items and return indexes alert

I have json and i render items with flatlist component. I have component "TouchableOpacity" and I need to highlight some items from flatlist. After highlighting I need display choosen items IDs to alert after I press button. Can someone help me with this issue?
export default class Grid extends Component {
constructor(props) {
super(props)
this.state = {
selectId: [],
countIds: 0,
}
}
renderItem = ({item}) => {
return(
<View style={styles.container}>
<TouchableOpacity onPress={() => this.highlightItem(item.id)} style={this.state.selectId === item.id ? styles.selected : null}>
<View style={styles.viewContainer}>
<Image source={{uri: item.imageUrl}} style={styles.imageContainer}/>
<Text>{item.name}</Text>
</View>
</TouchableOpacity>
</View>
)
}
highlightItem = (id) => {
console.log(id)
this.setState({
selectId: [...this.state.selectId, " " + id],
countIds: this.state.selectId.length + 1
})
}
selectedItems = () => {
Alert.alert(
'Data alert',
`Count of items: ${this.state.countIds} \nIDs items selected: ${this.state.selectId}`,
[
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
},
{
text: 'OK',
onPress: () => console.log('OK Pressed')
},
],
{cancelable: false},
)
}
render() {
return(
<View>
<FlatList
data={dataSource}
extraData={this.state.selectId}
renderItem={this.renderItem}
keyExtractor={(item, index) => index.toString()}
numColumns={columnNumber}
ListFooterComponent={this.renderButton}
/>
</View>
)
}
}

Categories