I am creating a relatively basic website that provides a survey to users. But I've run into a dead end at the moment trying to figure a way to have the next question dependent on the answer to the previous question. So far I have a separate page holding an array of roughly 40 questions, a component that maps each question with its text and answer, and the page where they are rendered.
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>
);
}
}
this method so far basically just lists all the questions through the component. I just can't work out how to go about changing it so as instead of listing all the questions initially, a question is added depending on the previous answer. For example, if the user answered question 1 with younger than 15 the next question would be question 3.
Any help would be greatly appreciated!
There were some syntax errors in your original code to begin with.
I refactored things a bit:
QuestionPage
's state.condition
field, which is a function that returns whether or not this question should be shown.NB: The below is dry-coded so there might be some silly typos or such in there.
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>
);
}
}
You actually want to build a decision tree to resolve that issue, for an example, you can have all the questions in the array and having a requireResponses[]
field
e.g:
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 }],
}
];
and compare the questionId
with the requireResponses
.
You can also have a look to that library who can help you a lot to develop your app.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With