Reputation: 1704
This is my code:
import React from "react";
import { View, StyleSheet, StatusBar, Text, SafeAreaView } from "react-native";
import { Button, ButtonContainer } from "../components/Button";
import { Alert } from "../components/Alert";
import firebase from "../config/firebase";
import "firebase/firestore";
const styles = StyleSheet.create({
container: {
backgroundColor: "red",
flex: 1,
paddingHorizontal: 20
},
text: {
color: "#fff",
fontSize: 25,
textAlign: "center",
letterSpacing: -0.02,
fontWeight: "600"
},
safearea: {
flex: 1,
marginTop: 100,
justifyContent: "space-between"
}
});
class Quiz extends React.Component {
state = {
correctCount: 0,
totalCount: 0,
activeQuestionIndex: 0,
answered: false,
answerCorrect: false,
questions: []
};
async componentDidMount() {
await this.questions();
}
questions = async () => {
const documents = await firebase
.firestore()
.collection("questions")
.where("quizId", "==", this.props.navigation.getParam("uid"))
.get();
const questions = documents.docs.map(doc => {
return { uid: doc.id, ...doc.data() };
});
return this.setState({ questions });
};
answer = correct => {
this.setState(
state => {
const nextState = { answered: true };
if (correct) {
nextState.correctCount = state.correctCount + 1;
nextState.answerCorrect = true;
} else {
nextState.answerCorrect = false;
}
return nextState;
},
() => {
setTimeout(() => this.nextQuestion(), 750);
}
);
};
nextQuestion = () => {
this.setState(state => {
const nextIndex = state.activeQuestionIndex + 1;
if (nextIndex >= state.totalCount) {
return this.props.navigation.navigate("Result", {
correct: this.state.correctCount
});
}
return {
activeQuestionIndex: nextIndex,
answered: false
};
});
};
render() {
console.log(this.state.questions);
const questions = this.props.navigation.getParam("questions", []);
const question = questions[this.state.activeQuestionIndex];
return (
<View
style={[
styles.container,
{ backgroundColor: this.props.navigation.getParam("color") }
]}
>
<StatusBar barStyle="light-content" />
<SafeAreaView style={styles.safearea}>
<View>
<Text style={styles.text}>
{this.state.activeQuestionIndex + 1}.{question.question}
</Text>
<ButtonContainer>
{question.answers.map(answer => (
<Button
key={answer.id}
text={answer.text}
onPress={() => this.answer(answer.correct)}
/>
))}
</ButtonContainer>
</View>
{/* <Text style={styles.text}>
{`${this.state.correctCount}/${this.state.totalCount}`}
</Text> */}
</SafeAreaView>
{/* <Alert
correct={this.state.answerCorrect}
visible={this.state.answered}
/> */}
</View>
);
}
}
export default Quiz;
console.log
is fired two time. First time it return empty array and the second time it return the expected elements. As I understand, because of the async
on my componentDidMount
the second time is rendered because of the questions
method, where the state is changed in it. Did I understand it right ? And my question is how can I prevent that ? Because this way error is thrown on the first render because the code below breaks. Thank you!
Upvotes: 0
Views: 35
Reputation: 169388
Your questions are being loaded asynchronously after mount.
I'd suggest changing your initial questions
to be undefined
, e.g.
state = {
...
questions: undefined
};
and checking for that in your render. If questions
is undefined, things are still being loaded.
render() {
if(this.state.questions === undefined) return null;
// ...
Upvotes: 1