使用 React 创建一个调查,但一直在寻找一种方法来根据某些回答提出问题

Creating a survey using React but stuck finding a way to have questions dependent on certain responses

我正在创建一个向用户提供调查的相对基本的网站。但是我现在 运行 陷入了死胡同,试图找到一种方法让下一个问题依赖于上一个问题的答案。到目前为止,我有一个包含大约 40 个问题的数组的单独页面,一个将每个问题与其文本和答案映射的组件,以及呈现它们的页面。

const questionArray = [
  {
    question: "how old are you?",
    answers: [
      "younger than 15",
      "between 15 and 20",
      "older than 20",
    ],
    questionId: 1,
  },
  {
    question: "are you a student?",
    answers: ["yes", "no"],
    questionId: 2,
  },
  {
    question: "where do you live",
    answers: ["QLD", "NSW", "VIC", "ACT", "NT", "TAS", "WA"],
    questionId: 3,
  },
];

const QuestionComponent = ({ question, options, selected }) => {
  const [answer, setAnswer] = useState(options);
  return (
    <div>
      {question}
      {answer.map((text, index) => (
        <button
          key={index}
          onClick={() => {
            setAnswer([text]);
            selected(text);
          }}
        >
          {text}
        </button>
      ))}
    </div>
  );
};

class QuestionPage extends Component {
  state = {
    questions: [],
  };

  getQs = () => {
    this.setState({ questions: questionArray });
  };

  componentDidMount() {
    this.getqs();
  }

  render() {
    return (
      <div>
        {this.state.questions.map(
          ({ question, answers, questionId }) => (
            <QuestionComponent
              question={question}
              options={answers}
              key={questionId}
            />
          ),
        )}
      </div>
    );
  }
}

这个方法到目前为止基本上只是通过组件列出所有问题。我只是想不出如何改变它,而不是一开始就列出所有问题,而是根据以前的答案添加一个问题。例如,如果用户回答问题 1 时年龄小于 15 岁,则下一个问题将是问题 3。

如有任何帮助,我们将不胜感激!

您实际上想构建一个决策树来解决该问题,例如,您可以将所有问题都放在数组中并有一个 requireResponses[] 字段

例如:

const questionArray = [
     {
          question: "how old are you?",
          answers: ['younger than 15', 'between 15 and 20', 'older than 20'],
          questionId: 1
     },
     {
          question: "are you a student?",
          answers: ['yes', 'no'],
          questionId: 2,
          requireResponses: [{ questionId: 1, answer: 0 }],
     },
     {
          question: "where do you live",
          answers: ['QLD', 'NSW', 'VIC', 'ACT', 'NT', TAS', WA'],
          questionId: 3,
          requireResponses: [{ questionId: 1, answer: 1 }, { questionId: 2, answer: 1 }],
     }
];

并将 questionIdrequireResponses 进行比较。

你也可以看看that library谁可以帮助你开发你的应用程序。

开始时您的原始代码中存在一些语法错误。

我重构了一下:

  • 问题不是状态的一部分;问题本身不应该改变。
  • 答案现在存储在 QuestionPage 的状态中。
  • 问题有一个可选的 condition 字段,这是一个 returns 是否应显示此问题的功能。

注意:以下是干编码,因此其中可能存在一些愚蠢的拼写错误等。

const questionArray = [
  {
    question: "how old are you?",
    answers: [
      "younger than 15",
      "between 15 and 20",
      "older than 20",
    ],
    questionId: 1,
  },
  {
    question: "are you a student?",
    answers: ["yes", "no"],
    questionId: 2,
    condition: ({ answers }) => answers[1] != "older than 20",
  },
  {
    question: "where do you live",
    answers: ["QLD", "NSW", "VIC", "ACT", "NT", "TAS", "WA"],
    questionId: 3,
  },
];

const QuestionComponent = ({ question, answer, onSelect }) => {
  const { question, answers } = question;
  return (
    <div>
      {question}
      {answers.map((text, index) => (
        <button
          key={index}
          onClick={() => {
            onSelect(text);
          }}
        >
          {text}
        </button>
      ))}
    </div>
  );
};

class QuestionPage extends Component {
  state = {
    answers: {},
  };

  render() {
    const questions = questionArray.filter(q => {
      if (!q.condition) {
        // no condition set; always visible
        return true;
      }
      return q.condition({ answers });
    });
    return (
      <div>
        {questions.map(question => (
          <QuestionComponent
            question={question}
            answer={this.state.answers[question.questionId]}
            key={question.questionId}
            onSelect={answer => {
              const answers = {
                ...this.state.answers,
                [question.questionId]: answer,
              };
              this.setState({ answers });
            }}
          />
        ))}
      </div>
    );
  }
}