渲染方法被触发两次

时间:2020-04-13 17:09:53

标签: reactjs react-native

这是我的代码:

   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被触发两次。第一次返回空数组,第二次返回期望的元素。据我了解,由于async上的componentDidMount的存在,第二次渲染是因为questions方法的状态发生了变化。我明白吗?我的问题是如何防止这种情况发生?因为这种方式会因为下面的代码中断而在第一个渲染器上引发错误。谢谢!

1 个答案:

答案 0 :(得分:1)

您的问题将在安装后异步加载。

我建议将您的初始questions更改为undefined,例如

  state = {
    ...
    questions: undefined
  };

并在渲染中进行检查。如果questions未定义,则仍在加载内容。

render() {
  if(this.state.questions === undefined) return null;
  // ...