I am new to coding. Currently tryin to make a mobile app in react-native + firebase.
I am stuck at some really simple ( as i think ) stage, but spent a couple of days now but cannot find an answer.
In my app, user can create or enter room. Once created, room generates specific folder in firebase.
Creating and entering rooms work fine.
But whhen user enters a new room , he observes the state from the previous room even though it suppose to be blank as this is his first entry.
I dont understand how to solve this problem, absolutely crying now. A
Any help is appreciated.
This is a part of code where state is saved:
class ChatRoom extends React.Component {
constructor(zaza) {
super(zaza);
this.state = {
allTasksComplete: false,
task1: false,
task2: false,
task3: false,
task4: false,
task5: false,
task6: false,
task7: false,
finishedTasks: null,
zozo: false,
newRoomName: '',
creator: '',
};
}
generateTask = async (taskIndex, taskName,) => {
const creatorCheck = await AsyncStorage.getItem('nickname')
this.setState({creator: creatorCheck})
const nicknameSnap = await collectionRef.where('roomName', '==', this.state.newRoomName).get()
const nickCheck = nicknameSnap.docs[0].data()
if(nickCheck.creator === this.state.creator) {
firestore()
.collection('Rooms')
.doc(this.state.newRoomName)
.collection('Alpha')
.doc(taskIndex)
.set({
taskText: taskName,
})
.then(() => {
console.log('Task added')
})
}
else {
firestore()
.collection('Rooms')
.doc(this.state.newRoomName)
.collection('Beta')
.doc(taskIndex)
.set({
taskText: taskName,
})
.then(() => {
console.log('Task added')
})
} }
async componentDidMount() {
try {
const trytextx = await AsyncStorage.getItem('currentRoom')
const trial = JSON.parse(trytextx)
const maybe1 = await AsyncStorage.getItem('task1')
const string1 = JSON.parse(maybe1)
const maybe2 = await AsyncStorage.getItem('task2')
const string2 = JSON.parse(maybe2)
this.setState({newRoomName: trial})
if (string1 === false) {
this.setState({task1: false})
} else {
this.setState({ task1: string1 })
}
if (string2 === false) {
this.setState({task2: false})
} else {
this.setState({ task2: string2 })
}
} catch (e) {
console.log(e)
}
db.collection('Rooms')
.doc('RRN')
.collection('Alpha')
.get()
.then(snapshot => {
const tasks = []
snapshot.forEach(doc => {
const data = doc.data()
tasks.push(data)
})
this.setState({
finishedTasks: tasks
})
})
}
taskOne() {
if (this.state.task1) {
return (
<View>
<TaskOne />
<TouchableOpacity onPress={() => {
this.generateTask('Task1', 'First Task');
this.buttonTaskTwo()
}} raised='true' >
<View style={styles.buttonDone2}>
<Text style={styles.buttonText2}>
Выполнено
</Text>
</View>
</TouchableOpacity>
</View>
)
}
}
taskTwo() {
if (this.state.task2) {
return (
<View>
<TaskTwo />
<TouchableOpacity onPress={() => {
this.generateTask('Task2', 'Second Task');
this.buttonTaskThree()
}}>
<View style={styles.buttonDone2}>
<Text style={styles.buttonText2}>
Выполнено
</Text>
</View>
</TouchableOpacity>
</View>
)
}
}
CongratsMsg() {
if (this.state.allTasksComplete) {
return (
<View>
<CongratsMsg />
<TouchableOpacity onPress={this.lastButton}>
<View style={styles.buttonDone}>
<Text style={styles.buttonText2}>
Получить
</Text>
</View>
</TouchableOpacity>
</View>
)
}
}
lastMessage() {
if (this.state.zozo) {
return (
<View style={styles.MessageBG}>
<View >
{
this.state.finishedTasks.map(task => {
return (
<View>
<Text style={styles.MessageText}>*** {task.taskText} ***</Text>
</View>
)
})
}
</View>
</View>
)
}
}
lastButton = async () => {
this.setState({ zozo: true })
}
buttonTaskOne = async () => {
this.setState({ task1: true })
try {
await AsyncStorage.setItem('task1', JSON.stringify(true))
/* firestore()
.collection('Rooms')
.doc(this.state.newRoomName)
.set({
firstVisit: false
}, { merge: true }) */
} catch (e) {
console.log(e)
}
}
buttonTaskTwo = async () => {
this.setState({ task2: true })
try {
await AsyncStorage.setItem('task2', JSON.stringify(true))
} catch (e) {
console.log(e)
}
}
buttonCongrats = () => {
this.setState({ allTasksComplete: true })
}
render() {
return (
<ImageBackground source={bgImage} style={styles.backgroundContainer}>
<ScrollView style={styles.secondBg}>
<DefaultMsg />
<TouchableOpacity onPress={this.buttonTaskOne}>
<View style={styles.buttonDone}>
<Text style={styles.buttonText2}>
Начать!
</Text>
</View>
</TouchableOpacity>
<View>
{this.taskOne()}
</View>
<View>
{this.taskTwo()}
</View>
<View>
{this.CongratsMsg()}
</View>
<View>
{this.lastMessage()}
</View>
</ScrollView>
</ImageBackground>
)
}
}
I end up saving my state in firebase instead of asyncstorage.
Related
I am very new to React Native and still in exploring phase but I am using it for my school project. How do I translate my array of prediction using react-native-translator package? Theres only examples by using Hooks but Im using class component. This is how I get my array of prediction output:
<View style={styles.predictionWrapper}>
{isModelReady && image && (
<Text style={styles.text}>
Predictions: {predictions ? '' : 'Predicting...'}
</Text>
)}
{isModelReady &&
predictions &&
predictions.map(p => this.renderPrediction(p))}
</View>
Now I want to do translation below it. Something like this:
<View>
<Translator
from="en"
to="ms"
value={isModelReady &&
predictions &&
predictions.map(p => this.renderPrediction(p))}
onTranslated={}
/>
<Text>{result}</Text>
</View>
);
But I am not sure how should I do it with class component. I really hope someone can give me an idea how to do it.
This is my full code:
class Home extends React.Component {
state = {
isTfReady: false,
isModelReady: false,
predictions: null,
image: null
}
async componentDidMount() {
await tf.ready()
this.setState({
isTfReady: true
})
this.model = await mobilenet.load()
this.setState({ isModelReady: true })
//Output in Expo console
console.log(this.state.isTfReady)
this.getPermissionAsync()
}
getPermissionAsync = async () => {
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL)
if (status !== 'granted') {
alert('Sorry, we need camera roll permissions to make this work!')
}
}
}
imageToTensor(rawImageData) {
const TO_UINT8ARRAY = true
const { width, height, data } = jpeg.decode(rawImageData, TO_UINT8ARRAY)
// Drop the alpha channel info for mobilenet
const buffer = new Uint8Array(width * height * 3)
let offset = 0 // offset into original data
for (let i = 0; i < buffer.length; i += 3) {
buffer[i] = data[offset]
buffer[i + 1] = data[offset + 1]
buffer[i + 2] = data[offset + 2]
offset += 4
}
return tf.tensor3d(buffer, [height, width, 3])
}
classifyImage = async () => {
try {
const imageAssetPath = Image.resolveAssetSource(this.state.image)
const response = await fetch(imageAssetPath.uri, {}, { isBinary: true })
const rawImageData = await response.arrayBuffer()
const imageTensor = this.imageToTensor(rawImageData)
const predictions = await this.model.classify(imageTensor)
this.setState({ predictions })
console.log(predictions)
} catch (error) {
console.log(error)
}
}
selectImage = async () => {
try {
let response = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3]
})
if (!response.canceled) {
const source = { uri: response.uri }
this.setState({ image: source })
this.classifyImage()
}
} catch (error) {
console.log(error)
}
}
renderPrediction = prediction => {
return (
<Text key={prediction.className} style={styles.text}> {prediction.className} </Text>
)
}
translateTo() {
const [value, setValue] = useState('renderPrediction');
const [result, setResult] = useState('');
return (
<View>
<Translator
from="en"
to="fr"
value={value}
onTranslated={(t) => setResult(t)}
/>
<TextInput value={value} onChangeText={(t) => setValue(t)} />
<Text>{result}</Text>
</View>
);
}
// naviScreen = () => {
// const navigation = useNavigation();
// navigation.navigate('ScanScreen');
// }
render() {
const { isTfReady, isModelReady, predictions, image } = this.state;
return (
<View style={styles.container}>
<StatusBar barStyle='light-content' />
<View style={styles.loadingContainer}>
<View style={styles.loadingModelContainer}>
{(isTfReady && isModelReady) ? (
<Text style={styles.text}> APP IS READY FOR SCANNING! </Text>) : <ActivityIndicator size='small' />}
</View>
</View>
<TouchableOpacity
style={styles.imageWrapper}
onPress={isModelReady ? this.selectImage : undefined}>
{image && <Image source={image} style={styles.imageContainer} />}
{isModelReady && !image && (
<Text style={styles.transparentText}>Tap to choose image</Text>
)}
</TouchableOpacity>
<View style={styles.predictionWrapper}>
{isModelReady && image && (
<Text style={styles.text}>
Predictions: {predictions ? '' : 'Predicting...'}
</Text>
)}
{isModelReady &&
predictions &&
predictions.map(p => this.renderPrediction(p))}
</View>
<View style={styles.bottom}>
<Button style={styles.text} title='SAVE THIS IMAGE' ></Button>
</View>
<Button title='LIVE Scan Now' onPress={() => this.props.navigation.navigate('ScanScreen')}></Button>
</View>
)
}
}
Refactored translation code for class-based component:
class Home extends React.Component {
state = {
isTfReady: false,
isModelReady: false,
predictions: null,
image: null,
textToTranslate: "",
translationResult: "",
};
async componentDidMount() {
await tf.ready();
this.setState({
isTfReady: true,
});
this.model = await mobilenet.load();
this.setState({ isModelReady: true });
//Output in Expo console
console.log(this.state.isTfReady);
this.getPermissionAsync();
}
getPermissionAsync = async () => {
if (Constants.platform.ios) {
const { status } = await Permissions.askAsync(Permissions.CAMERA_ROLL);
if (status !== "granted") {
alert("Sorry, we need camera roll permissions to make this work!");
}
}
};
imageToTensor(rawImageData) {
const TO_UINT8ARRAY = true;
const { width, height, data } = jpeg.decode(rawImageData, TO_UINT8ARRAY);
// Drop the alpha channel info for mobilenet
const buffer = new Uint8Array(width * height * 3);
let offset = 0; // offset into original data
for (let i = 0; i < buffer.length; i += 3) {
buffer[i] = data[offset];
buffer[i + 1] = data[offset + 1];
buffer[i + 2] = data[offset + 2];
offset += 4;
}
return tf.tensor3d(buffer, [height, width, 3]);
}
classifyImage = async () => {
try {
const imageAssetPath = Image.resolveAssetSource(this.state.image);
const response = await fetch(imageAssetPath.uri, {}, { isBinary: true });
const rawImageData = await response.arrayBuffer();
const imageTensor = this.imageToTensor(rawImageData);
const predictions = await this.model.classify(imageTensor);
this.setState({ predictions });
console.log(predictions);
} catch (error) {
console.log(error);
}
};
selectImage = async () => {
try {
let response = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
});
if (!response.canceled) {
const source = { uri: response.uri };
this.setState({ image: source });
this.classifyImage();
}
} catch (error) {
console.log(error);
}
};
renderPrediction = (prediction) => {
return (
<Text key={prediction.className} style={styles.text}>
{" "}
{prediction.className}{" "}
</Text>
);
};
renderTranslation = () => {
return (
<View>
<Translator
from="en"
to="fr"
value={this.state.textToTranslate}
onTranslated={(text) => this.setState({ translationResult: text })}
/>
<TextInput
value={this.state.textToTranslate}
onChangeText={(text) => this.setState({ textToTranslate: text })}
/>
<Text>{this.state.translationResult}</Text>
</View>
);
};
// naviScreen = () => {
// const navigation = useNavigation();
// navigation.navigate('ScanScreen');
// }
render() {
const { isTfReady, isModelReady, predictions, image } = this.state;
return (
<View style={styles.container}>
<StatusBar barStyle="light-content" />
{this.renderTranslation()}
<View style={styles.loadingContainer}>
<View style={styles.loadingModelContainer}>
{isTfReady && isModelReady ? (
<Text style={styles.text}> APP IS READY FOR SCANNING! </Text>
) : (
<ActivityIndicator size="small" />
)}
</View>
</View>
<TouchableOpacity
style={styles.imageWrapper}
onPress={isModelReady ? this.selectImage : undefined}
>
{image && <Image source={image} style={styles.imageContainer} />}
{isModelReady && !image && (
<Text style={styles.transparentText}>Tap to choose image</Text>
)}
</TouchableOpacity>
<View style={styles.predictionWrapper}>
{isModelReady && image && (
<Text style={styles.text}>
Predictions: {predictions ? "" : "Predicting..."}
</Text>
)}
{isModelReady &&
predictions &&
predictions.map((p) => this.renderPrediction(p))}
</View>
<View style={styles.bottom}>
<Button style={styles.text} title="SAVE THIS IMAGE"></Button>
</View>
<Button
title="LIVE Scan Now"
onPress={() => this.props.navigation.navigate("ScanScreen")}
></Button>
</View>
);
}
}
I am tring to make a simple audio button So when u trigger the button should play the sound and toggle the button until now everything works fine but no sound output
I am using react-native-sound-player
some informations
npm Packages:
react: 16.13.1 => 16.13.1
react-native: 0.63.2 => 0.63.2
Node: 14.16.1
Yarn: 1.22.10
npm: 6.14.12
const [isPlaying, setIsPlaying] = useState(false);
const [loadFinished, setloadFinshid] = useState(false);
const loadURI = async () => {
if (props.uri !== '') {
try {
await SoundPlayer.loadUrl(props.uri)
const onFinishedLoadingURLSubscription = SoundPlayer.addEventListener('FinishedLoadingURL', ({ success, url }) => {
if (success) {
setloadFinshid(true)
}
})
} catch (error) {
console.log(e)
}
}
}
useEffect(() => {
if (isPlaying) {
console.log('A')
playURI()
} else {
console.log('B')
}
loadURI()
return () => {
Toast.hide()
SoundPlayer.stop()
onFinishedPlayingSubscription.remove();
}
}, [props.uri, isPlaying])
const playURI = () => {
if (loadFinished) {
try {
SoundPlayer.play(props.uri)
}
catch (e) {
console.log(e)
}
}
}
const Next = () => {
SoundPlayer.stop()
setIsPlaying(false)
props.navigation.navigate('stepOne', { props })
}
const stopSound = () => {
SoundPlayer.stop()
}
const onFinishedPlayingSubscription = SoundPlayer.addEventListener('FinishedPlaying', ({ success }) => {
if (success) {
setIsPlaying(false)
}
})
That's the view side
<View style={styles.wrapper}>
<Header pointer={1} navigation={props.navigation} />
<View style={styles.top}>
<Image source={require('../../assets/listen.png')} style={styles.image} />
</View>
<View style={styles.bottom}>
<Text style={styles.title}>{props.title}</Text>
<View style={styles.btnHandler}>
{
!loadFinished ?
<ActivityIndicator size="large" color="#fff" />
:
<>
{!isPlaying ?
<Icone.Button
name="play"
backgroundColor="transparent"
color="#fff"
iconStyle={{ marginRight: 0 }}
onPress={() => setIsPlaying(true)}
style={styles.btn}
></Icone.Button>
:
<Icone.Button
name="pause"
backgroundColor="transparent"
color="#fff"
iconStyle={{ marginRight: 0 }}
onPress={() => setIsPlaying(false)}
style={styles.btn}
></Icone.Button>
}
</>
}
</View>
</View>
<NextButton data={props} onPress={Next} />
</View>
)
}```
You can use "TrackPlayer"
Click here to navigate react-native-track-player
After Installing
import TrackPlayer, {State, Event} from 'react-native-track-player';
Use
var track = { url: "Use Your URL here" } // Your can also use many Parameters like "title", "artist", "album", "genre"
TrackPlayer.add([track]); // Add your Track
TrackPlayer.play(); // Can play your Track Like this.
TrackPlayer.destroy(); // Can Destroy the Track Like this.
TrackPlayer.getPosition().then(result => {
"here you will get the current Playing Position of Audio In", result
});
TrackPlayer.getDuration().then(result => {
"here you will get the Total TrackPlayer Duration In", result
});
im trying to filter my api array in this just for the users witch speciality == Dermatologista, can you help me?
export default class Dermatologistas extends Component{
state ={
errorMessage: null,
users: []
}
here I create the async function that is getting the users
getUserList = async () => {
try {
const response = await api.get('/auth/list');
const { users } = response.data
console.log(response.data)
this.setState({ users });
} catch (response) {
this.setState({ errorMessage: response.data.error });
}
};
componentDidMount() {
this.getUserList()
}
here it renders all users and not filter, how can I do this ?
render(){
const users = this.state.users
console.log(users)
return(
<View >
{ this.state.errorMessage && <Text>{ this.state.errorMessage }</Text> }
{this.state.users.map(user => (
<View key={user._id} style={{marginTop: 15, alignItems: 'center'}}>
<Text>{user.title}</Text>
<Text>{user.speciality}</Text>
<Button title = 'View Profile'onPress ={() =>
this.props.navigation.navigate('Profile')}/>
</View>
))}
</View>
)
}
}
You can create a function which takes the data that's being received along with the parameter through which you want to filter the data.
const filterBySpeciality = (data, speciality) => data.filter(d => d.speciality == speciality)
let data = [{speciality: "Ortho", title: "Chief Surgeon"}, {speciality: "Dermatologista", title: "Specialist"}];
console.log(filterBySpeciality(data, "Dermatologista"));
So, in your case you can call filterBySpeciality(data, "Dermatologista") in your render function and use the result for populating the View like below.
const filterBySpeciality = (data, speciality) => data.filter(d => d.speciality == speciality)
render() {
const filteredData = this.filterBySpeciality(this.state.users, "Dermatologista");
return(
<View >
{ this.state.errorMessage && <Text>{ this.state.errorMessage }</Text> }
{/* Here I have changed this.state.users to filteredData */}
{filteredData.map(user => (
<View key={user._id} style={{marginTop: 15, alignItems: 'center'}}>
<Text>{user.title}</Text>
<Text>{user.speciality}</Text>
<Button title = 'View Profile'onPress ={() =>
this.props.navigation.navigate('Profile')}/>
</View>
))}
</View>
)
}
Just put condition before rendering to data.
getUserList = async () => {
try {
const response = await api.get('/auth/list');
const usersData = response.data
const users = usersData.filter((user: any) => {
if (user.speciality === 'Dermatologista') return user;
})
console.log(users);
this.setState({ users });
} catch (response) {
this.setState({ errorMessage: response.data.error });
}
};
componentDidMount() {
this.getUserList()
}
Or you can try something like this :
render(){
const usersData = this.state.users
const users = usersData.filter((user: any) => {
if (user.speciality === 'Dermatologista') return user;
})
console.log(users)
return(
<View >
{ this.state.errorMessage && <Text>{ this.state.errorMessage }</Text> }
{this.state.users.map(user => (
<View key={user._id} style={{marginTop: 15, alignItems: 'center'}}>
<Text>{user.title}</Text>
<Text>{user.speciality}</Text>
<Button title = 'View Profile'onPress ={() =>
this.props.navigation.navigate('Profile')}/>
</View>
))}
</View>
)
}
}
in the view just this:
<View >
{ this.state.errorMessage && <Text>{ this.state.errorMessage }</Text> }
{this.state.users.filter(user => user.speciality === 'Dermatologista').map(user => (
<View key={user._id} style={{marginTop: 15, alignItems: 'center'}}>
<Text style={{fontWeight: 'bold', fontSize:20}}>{user.title}</Text>
<Text>{user.speciality}</Text>
<Button title = 'View Profile'onPress ={() => this.props.navigation.navigate('Profile')}/>
</View>
I'm getting the following warning in my react native app screen:
Warning: Cannot update during an existing state transition (such as within 'render'). Render functions should be a pure function of props and state.
As you see it seems to have something related with my getVolunteerDonations method.
Here´s my code:
export default class ProfileScreen extends React.Component {
constructor() {
super();
this.state = {
activeCard : null,
selectedIndex: 0,
user: null,
ongoingDonations: [],
finalizedDonations: [],
volunteerOngoingDonations: [],
deliveredDonations: [],
isLoadingDonations: true,
isLoadingDeliveries: true,
alertStatus: "",
alertTitle: "",
alertMessage: ""
};
this.getVolunteerDonations = this.getVolunteerDonations.bind(this);
this.getOngoingDonations = this.getOngoingDonations.bind(this);
this.displayDropdownAlert = this.displayDropdownAlert.bind(this);
}
loadUser(){
let userEmail = encodeURIComponent(auth().currentUser.email);
Promise.all([
fetch(API_URL + "/users?email=" + userEmail)
])
.then(([res1]) => Promise.all([res1.json()]))
.then(([data1]) => {
this.setState({
user: data1[0]
})})
.catch((error) => console.log(error))
}
componentDidMount(){
this.loadUser();
}
triggerReload (status, title, message) {
this.setState({
isLoadingDonations: true,
isLoadingDeliveries: true,
alertStatus: status,
alertTitle: title,
alertMessage: message
})
}
displayDropdownAlert(status, title, message) {
if(this.dropDownAlertRef) {
this.dropDownAlertRef.alertWithType(status, title, message);
}
}
getVolunteerDonations() {
if (this.state.user != null && this.state.user.category === "Voluntario" && this.state.isLoadingDonations === false
&& this.state.isLoadingDeliveries) {
const email = this.state.user.email.replace("+", "%2B");
return fetch(API_URL + "/donations?volunteer=" + email)
.then(response => response.json())
.then(volunteerDonations => {
let volunteerDonationsAux = [];
let volunteeerDonationsDone = [];
volunteerDonations.map(donation => {
if (donation.status === 'DELIVERED' || donation.status === 'CANCELLED-BY-USER') {
volunteeerDonationsDone.push(donation);
} else {
volunteerDonationsAux.push(donation);
}
})
this.setState({
volunteerOngoingDonations: volunteerDonationsAux,
deliveredDonations: volunteeerDonationsDone,
isLoadingDeliveries: false
});
});
} else if (this.state.user != null && this.state.user.category != "Voluntario" && this.state.isLoadingDeliveries) {
this.setState({
isLoadingDeliveries: false
});
}
}
render() {
if(this.state.alertStatus != "") {
this.displayDropdownAlert(this.state.alertStatus, this.state.alertTitle, this.state.alertMessage);
}
this.getOngoingDonations();
this.getVolunteerDonations();
let options;
let listData;
let itemType;
if (this.state.user != null) {
if (this.state.user.category == "Donante" || this.state.user.category == "Quiero ser Voluntario") {
options = ['Donaciones'];
listData = this.state.ongoingDonations;
itemType = "offer";
} else {
options = ['Entregas', 'Donaciones'];
if(this.state.selectedIndex == 0) {
listData = this.state.volunteerOngoingDonations;
itemType = "delivery";
} else {
listData = this.state.ongoingDonations;
itemType = "offer";
}
}
}
const {navigate} = this.props.navigation;
if (this.state.isLoadingDonations || this.state.isLoadingDeliveries){
return(
<ScrollView contentContainerStyle={{alignItems: "center", flex: 1, justifyContent: 'center'}}>
<Spinner isVisible={true} size={100} type={'Pulse'} color={'#013773'}/>
</ScrollView>
)
} else {
const getHeader = () => {
return <View>
<Ionicons name="ios-settings" size={40} color="#013773"
onPress={() => navigate('Configuración', {user: this.state.user, finalizedDonations: this.state.finalizedDonations, deliveredDonations: this.state.deliveredDonations})}
style={{position: "absolute", right: 10}}/>
<View style={{marginTop: 45, alignItems: "center"}}>
<View style={styles.avatarContainer}>
<Image style={styles.avatar}
source={require('../../../assets/logo.png')}/>
</View>
<Text style={styles.name}> {auth().currentUser.displayName} </Text>
</View>
<View style={styles.stat}>
<Text style={styles.statTitle}> {this.state.user.category === "Voluntario" ? "Voluntario": "Donante"} - {this.state.user.phone} </Text>
<Text style={styles.statTitle}> {this.state.user.email} - {this.state.user.address} </Text>
{this.state.user.category === "Donante" ? <Button
buttonStyle={styles.wantVolunteer}
title='Quiero ser voluntario' onPress={() => navigate("Quiero ser voluntario", {user: this.state.user, finalizedDonations: this.state.finalizedDonations, deliveredDonations: this.state.deliveredDonations})}/>
: null}
</View>
{this.renderSummary()}
{options.length > 1 ?
<SegmentedControlTab
values={options}
selectedIndex={this.state.selectedIndex}
onTabPress={this.handleIndexChange}
tabsContainerStyle={styles.tabsContainerStyle}
tabStyle={styles.tabStyle}
tabTextStyle={{fontSize: 18, color: '#013773'}}
activeTabStyle={{ backgroundColor: '#013773' }}
/> :
null}
</View>
}
const getFooter = () => {
if(listData.length <= 0){
return <View style={{alignItems: 'center'}}>
<Text style={styles.nostuff}> ¡Nada para mostrar! </Text>
</View>;
}
return null;
}
return (
<View>
<FlatList
data={listData}
renderItem={({ item }) => <ProfileItem itemType={itemType} item={item} volunteer="test" triggerAlert={this.displayDropdownAlert.bind(this)} updateParentState={this.triggerReload.bind(this)}/>}
keyExtractor={(item, index) => index.toString()}
ListHeaderComponent={getHeader}
ListFooterComponent={getFooter}
onRefresh={() => this.triggerReload("", "", "")}
refreshing={this.state.isLoadingDonations}
/>
<DropdownAlert ref={ref => this.dropDownAlertRef = ref} />
</View>
);
}
}
}
Sorry for the long code but I'm not sure what might be relevant or not. I tried to remove some functions to make it a little bit shorter.
As you see I call getVolunteerDonations inside my render method.
I think the issue may be that you are calling the getVolunteerDonations function within your render, but that function does setState. Whenever you setState, you re-render so it's a bit of a vicious cycle.
Are you sure you need to call the function within render?
I suggest you call the getVolunteerDonations function within componentDidMount or if you rely on the loadUser call first, then call getVolunteerDonations within a .then() of the loadUser function.
Been working on finding a way to delete the clicked on document using React Native and Cloud Firestore. I can't figure out a way to get the document id and then use it in my code to replace the value of deleteItemId. Any ideas?
My collection with a document showing:
My code:
componentDidMount(){
this.getItems();
const { currentUser } = firebase.auth();
this.setState({ currentUser });
}
getItems = async () => {
this.setState({ refreshing: true });
this.unsubscribe = await this.ref.onSnapshot((querySnapshot) => {
const todos = [];
querySnapshot.forEach((doc) => {
todos.push({
tips: doc.data().tips,
date: doc.data().date,
user: doc.data().user,
like: doc.data().like
})
})
this.setState({
refreshing: false,
getData: todos
})
})
}
deletePost = () => {
const deleteItemId = "SELECTED DOCUEMNT ID HERE";
firestore.collection("tips").doc(deleteItemId).delete().then(function() {
alert("deleted")
}).catch(function(error) {
alert("Error removing document: ", error);
});
}
renderItem = ({ item, index }) => {
let date = item.date;
return (
<View style={styles.tips}>
<View style={styles.wrapper}>
<View style={styles.profilePicture}>
<View></View>
</View>
<View style={styles.right}>
<Text style={styles.username}>#{item.user}</Text>
<Text style={styles.date}>{ moment(item.date).fromNow() }</Text>
</View>
</View>
<Text style={styles.text}>{item.tips}</Text>
<View style={styles.bar}>
<Text><Icon onPress={() => this.like()} style={styles.heart} type="Octicons" name="heart" /> {item.like}</Text>
<Text onPress={() => {
this.setModalVisible(true);
}}><Icon style={styles.comment} type="FontAwesome" name="comment-o" /> {item.replies}</Text>
<Text onPress={() => this.deletePost()}><Icon style={styles.settings} type="Octicons" name="kebab-vertical" /></Text>
</View>
</View>
)
}
Every time you push a TODO to todos, make sure to also include the document ID:
todos.push({
id: doc.id,
tips: doc.data().tips,
date: doc.data().date,
user: doc.data().user,
like: doc.data().like
})
Then when you render a TODO, you include the ID in the rendering output of the eleent:
<Text onPress={() => this.deletePost(styles.id)}>