Remove an item in AsyncStorage using FlatList - javascript

Sorry for the inexperience, but how do I remove an Item in Async Storage renderized in Flat List, for example:
This is my component that creates a flatlist
export default function Saved() {
const [colors, setColors] = useState([]);
useEffect(() => {
async function getStorage() {
const nomeStorage = await AsyncStorage.getAllKeys();
if (nomeStorage != null) {
setColors(nomeStorage);
}
}
getStorage();
}, [colors])
return (
<View style={styles.body}>
<FlatList
data={colors}
keyExtractor={(item) => item}
renderItem={({ item }) => <Saveds data={item} />}
/>
</View>
);
}
and this is my FlatList renderized component
export default function Saveds(props) {
return (
<View>
<View style={styles.Boxes}>
<Box color={props.data}>
<Badge
badgeStyle={styles.badge}
value={<Text style={styles.color}>{props.data}</Text>}
/>
</Box>
<TouchableOpacity style={styles.btn}>
<Icon name={'trash-outline'} color={'#FFF'} size={30} />
</TouchableOpacity>
</View>
</View>
);
}
I need one way to when I click in my TouchableOpacity, I delete the selected data in my AsyncStorage.
The name in my AsyncStorage is the same as the value, so I can delete the AsyncStorage getting the value of my props.data.
Anyone can help me?

Deleting from your async storage should be as easy as just calling AsyncStorage.removeItem(key)
I had some similar functionality in an app that I made a while ago, I attached the delete function call to the onLongPress prop of touchableOpacity:
<TouchableOpacity
onPress={() => navigation.navigate('UserScreen', data)}
onLongPress={handleLongPress}>
<View style={styles.container}>
// ...
</View>
</TouchableOpacity>
And earlier in the component, I defined a function that handles the deleting:
const handleLongPress = async () => {
// In your instance, you should be OK to replace data.key with props.data
await AsyncStorage.removeItem(data.key);
/* I then had another function that was passed in as a prop
to update another component when the deletion had taken place */
await onChange();
};

Related

React Native Firebase Firestore data fetching with empty spaces

I have created 3 documents in Firestore database, each document has different data.
but When I add different data on different document ids then I am getting blank spaces, and those spaces are generated automatically for other document ids which I already created previously.
Document 1 should be shown on First screen and document 2 should show on screen two. I mean each document's data should show on its own screen. please check the image link below-
First Screen
import React, { useState, useEffect } from 'react';
import {View, Button, Text, FlatList, StyleSheet, Pressable, TouchableOpacity} from 'react-native'
import {firebase} from '../config';
const Testing = ({ navigation }) =>{
const [users, setUsers] = useState([]);
const todoRef = firebase.firestore().collection('testing');
useEffect(() => {
todoRef.onSnapshot(
querySnapshot => {
const users = []
querySnapshot.forEach((doc) => {
const { One, Two, Three
} = doc.data()
users.push({
id: doc.id,
One, Two, Three
})
})
setUsers(users)
}
)
}, [])
return (
<View style={{ flex:1,}}>
<FlatList
style={{height: '100%'}}
data={users}
numColumns={1}
renderItem={({item}) => (
<Pressable >
<View style={styles.viewOne}>
<View>
<Text style={[styles.card, styles.title]}>{item.One}</Text>
<Text style={styles.text}>{item.Two}</Text>
<Text style={styles.text}>{item.Three}</Text>
</View>
</View>
</Pressable>
)} />
</View>
);}
export default Testing;
*Second Screen*
import React, { useState, useEffect } from 'react';
import {View, Button, Text, FlatList, StyleSheet, Pressable, TouchableOpacity} from 'react-native'
import {firebase} from '../config';
const TestingDocs = ({ navigation }) =>{
const [users, setUsers] = useState([]);
const todoRef = firebase.firestore().collection('testing');
useEffect(() => {
todoRef.onSnapshot(
querySnapshot => {
const users = []
querySnapshot.forEach((doc) => {
const { DocsOne, DocsTwo, DocsThree,
} = doc.data()
users.push({
id: doc.id,
DocsOne, DocsTwo, DocsThree,
})
})
setUsers(users)
}
)
}, [])
return (
<View style={{ flex:1,}}>
<FlatList
style={{height: '100%'}}
data={users}
numColumns={1}
renderItem={({item}) => (
<Pressable >
<View style={styles.viewOne}>
<View>
<Text style={[styles.card, styles.title]}>{item.DocsOne}</Text>
<Text style={styles.text}>{item.DocsTwo}</Text>
<Text style={styles.text}>{item.DocsThree}</Text>
</View>
</View>
</Pressable>
)} />
</View>
);}
export default TestingDocs;
You must have seen this Answer on your another Post :
It looks like you've incomplete or "optional" data in your backend. If
you don't want to render empty fields you can conditionally render
them.
For the users data that is missing both properties you can filter
the data prop.
Example:
<FlatList
data={users.filter(({ One, five }) => One || five)}
renderItem={({ item }) => (
<View style={{ .... }}>
{item.One && <Text>ID: {item.One}</Text>}
{item.five && <Text>Name: {item.five}</Text>}
</View>
)}
/>
You can also refer to this Answer:
Its as a result of performance issues with the FlatList component but
you can add the following props to your FlatList Component, it would
help solve the problem. They are:
i. removeClippedSubviews.
Set this to true, it comes with a default of false.
ii. windowSize. Set this to a number like say 30
iii. maxToRenderPerBatch. This controls the number of items rendered per batch, which is the next chunk of items rendered on every
scroll.
<FlatList
data={this.state.contacts}
removeClippedSubviews={true}
maxToRenderPerBatch={60}
windowSize={30}
ListHeaderComponent={headerComponent}
contentContainerStyle={{ paddingBottom: 10 }}
renderItem={({ item }) => (
<View>
{item}
</View>
)}
numColumns={1}
keyExtractor={(item, index) => String(index)}
/>
For more information, you can refer to the blog which explains how to use react hooks with firebase firestore.

How to render component via FlatList?

Using react native with typescript and redux toolkit
Hi I'm bothering with render a list of messages via FlatList. By ScrollView everything rendering good but I need to implement infiniti scroll. So I'm doing something like this
const MessagesScreen = () => {
const companyId = useAppSelector(getCompanyId);
const userId = useAppSelector(getUserId);
const {
data: messages,
isLoading,
refetch
} = useGetMessagesQuery({ userId, companyId });
useFocusEffect(refetch);
return (
<FlatList
data={messages}
renderItem={() => {
<Messages messages={messages} />;
}}
/>
);
};
In return() I'm trying to render FlatList with component Messages which is down here:
const Messages = ({ messages }: { messages: Message[] }) => {
const navigation =
useNavigation<RootStackScreenProps<'DrawerNavigator'>['navigation']>();
const { colors } = useTheme();
return (
<View style={styles.container}>
{messages.map(message => {
const createdAt = message.created_at;
const isRead = message.read;
const icon = isRead ? 'email-open-outline' : 'email-outline';
const onClick = () => {
navigation.navigate('Message', {
messageId: message.id
});
};
return (
<TouchableOpacity key={message.id} onPress={onClick}>
<View
style={[styles.message, { borderBottomColor: colors.separator }]}
>
<View style={styles.iconPart}>
<Icon
name={icon}
type="material-community"
style={
isRead
? { color: colors.separator }
: { color: colors.inputFocus }
}
size={24}
></Icon>
</View>
<View style={styles.bodyPart}>
<Text
numberOfLines={1}
style={[isRead ? styles.readSubject : styles.unReadSubject]}
>
{message.subject}
</Text>
<Text
numberOfLines={1}
style={[isRead ? styles.readBody : styles.unReadBody]}
>
{message.body}
</Text>
</View>
<View style={styles.datePart}>
<Text style={{ color: colors.shadow }}>
{dayjs(createdAt).fromNow()}
</Text>
</View>
</View>
</TouchableOpacity>
);
})}
</View>
);
};
Actually behaviour is just rendering white screen with error
Possible Unhandled Promise Rejection (id: 17):
Error: Objects are not valid as a React child (found: object with keys {id, msg_type, created_at, subject, body, author, company_id, read}). If you meant to render a collection of children, use an array instead.
there is problem with your call back function:
you are not returning Messages component
1:Remove curly braces
return (
<FlatList
data={messages}
renderItem={() => <Messages messages={messages}/> }
/>
);
2:Add return statement
return (
<FlatList
data={messages}
renderItem={() => {
return <Messages messages={messages} />;
}}
/>
);
Couple things:
You're using the renderItem callback incorrectly:
<FlatList
data={messages}
renderItem={() => {
// ^ ignoring the renderItem props
return <Messages messages={messages} />;
}}
/>
Here, for each item in the messages array, you're rendering a component and passing all the messages into it. So you'll get repeated elements.
The renderItem callback is passed {item, index} where item is the CURRENT item in the array (index is the index into the array)
See docs here:
https://reactnative.dev/docs/flatlist
The usual thing is the renderItem callback renders ONE item at a time, like this:
<FlatList
data={messages}
renderItem={({item}) => {
return <Message message={item} />;
}}
/>
e.g. I'd make a <Message/> component that renders one item only.

How to pass onPress to props.children?

I'm trying to make a wrapper component in react-native that I can pass down all its props to the children it wraps around. What I really want is to pass down all function props down to all its children. It looks something like this below. I want the onPress in Wrapper to be called when the TouchableOpacity is pressed.
I tried this below but it doesn't work
const Wrapper = ({children,...props})=>{
return <View {...props}>{children}</View>
}
const App = ()=>{
return (
<View style={{flex:1}}>
<Wrapper onPress={()=>{console.log(2)}}>
<TouchableOpacity/>
</Wrapper>
</View>
)
}
It looks like you're looking to map the children and apply the props to each one. That might look like this:
const Wrapper = ({children,...props})=>{
return (<>
{React.Children.map(children, child => (
React.cloneElement(child, {...props})
))}
</>);
}
(method of mapping the children borrowed from this answer)
const App = () => {
return (
<View style={{ flex: 1 }}>
<TouchableOpacity onPress={() => {
// do the action need here here
}}>
<Wrapper >
</Wrapper>
</TouchableOpacity>
</View>
)
}
I would advise you to use hooks function instead
If you try to reuse functions that are related
** useAdd.js **
export default () => {
const addFuction(a, b) => {
// do preprocessing here
return a + b
}
return [addFuction]
}
main componet
import useAdd from "/useAdd";
const App = () => {
const [addFuction] = useAdd()
return (
<View style={{ flex: 1 }}>
<TouchableOpacity onPress={() => {
addFuction(4,5)
}}>
...action component...
</TouchableOpacity>
</View>
)
}
console in useAdd hook.... to see visual changes use the react useState

Rendering Firebase data in map function

I'm trying to render data from a firebase get function but it isn't displaying anything. The images console.log displays 2 values but it doesn't get rendered on the page. Does anyone have suggestions why that is.
function cards(){
store.collection('users').get().then(snapshot => {
images = snapshot.docs.map(doc => doc.data().image)
console.log(images)
return images.map((doc) => {
return (
<Card style={[styles.card, styles.card1]}>
<Text style={styles.label}>A</Text>
</Card>
)
})
})
}
return (
<View>
<View style={styles.viewport}>
<CardStack style={styles.content}>
{cards()}
</CardStack>
</View>
</View>
)
}
You are trying to call a asynchrounous function and get a return from it by using a then. You will always get an undefined from it because the then finished when your function already returned undefined or in this case nothing.
Try it with using a state and handling the async call correctly like here:
import React, { useState, useEffect } from "react";
const YourComponent = () => {
const [list, setLits] = useState([]);
useEffect(() => {
const snapshot = await store.collection("users").get();
const images = [];
snapshot.docs.forEach((s) => {
images.push(doc.data().image);
});
setLits(images);
}, []);
return (
<View>
<View style={styles.viewport}>
<CardStack style={styles.content}>
{list.map((i) => {
return (
<Card style={[styles.card, styles.card1]}>
<Text style={styles.label}>A</Text>
</Card>
);
})}
</CardStack>
</View>
</View>
);
};

update setState instance in react native

I am trying to fetch images stored on firebase storage and display in react native app. the functions works to get the download URL of images but it doesn't merge previous state and update component, it just displays in only one image (due to useState). so as each image is fetched it displays the image in the same image component instead of creating a new component to display in
Code:
import React, {setState, useState} from 'react';
import {DrawerActions, useNavigation} from '#react-navigation/native';
const Gallery = () => {
const navigation = useNavigation();
const [downloadUrl, setDownloadUrl] = useState({url: undefined});
console.log(`URL should be undefined at this point ${downloadUrl}`);
function listFilesAndDirectories(reference, pageToken) {
return reference.list({pageToken}).then(result => {
result.items.forEach(ref => {
ref.getDownloadURL().then(url => {
// console.log(`Image URL is:\n ${url}`);
setDownloadUrl({url: url});
});
});
if (result.nextPageToken) {
return listFilesAndDirectories(reference, result.nextPageToken);
}
return Promise.resolve();
});
}
const storageReference = firebase
.storage()
.refFromURL('gs://ab404.appspot.com/images');
listFilesAndDirectories(storageReference).then(() => {
console.log('Started listing image download urls');
});
return (
<>
<StatusBar barStyle="dark-content" />
<SafeAreaView>
<View style={SharedStyles.header}>
<TouchableOpacity
onPress={() => {
navigation.dispatch(DrawerActions.openDrawer());
}}>
<Hamburg />
</TouchableOpacity>
<Header title="Gallery" />
</View>
<ScrollView contentInsetAdjustmentBehavior="automatic">
<View style={styles.container}>
<View style={styles.sectionContainer}>
<View>
<Text>
Welcome to the Abulad Gallery! Come back for more content....
</Text>
<Image
source={{uri: downloadUrl.url}}
style={styles.fetchedImage}
/>
</View>
</View>
</View>
</ScrollView>
</SafeAreaView>
</>
);
};
I have tried using the spread operator to get previous state and update as needed but I get an invalid attempt to spread a non-iterable instance
I need a way to make images appear in their component while updating url
Thanks

Categories