Creating a Sorting Hat Quiz Feature with React State

Christina Sohn
3 min readNov 3, 2020

--

For my Module 4 project at the Flatiron School, my partner and I used React to create a Harry Potter-themed sorting hat quiz. When a user logs in, they are taken to the beginning of the quiz. After they answer all the questions, the app informs them of which Hogwarts house they belonged to. The video demo is below:

In order to create this feature, there was important data that we needed to store in state within the main question container:

SQuestionContainer.js //Sorting Hat Question Containerstate = {questions: [],
currentQuestion: {
questionNumber: 1,
},
answeredQuestions: {
values: [],
}
};

The code above includes the following elements, which are stored in state:

1.) An array of questions (and their answers) fetched from the backend

When the page loads, the program will fetch the questions and answers from the backend on ComponentDidMount.

2.) The current question displayed on the screen

When a user clicks on an answer choice, the handleClick function will run. This function includes the following code (abbreviated from the original):

handleClick = () => {   let nextQuestionNumber = this.state.currentQuestion.questionNumber + 1;   if (nextQuestionNumber > this.state.questions.length) {
[...]
}
else{
this.setState({
currentQuestion: {
questionNumber: nextQuestionNumber,
}
}

The state of the current question will increment by one, and the page will conditionally render the current question. Additionally, because you now have the current page stored in state, you adjust the styling based on which page the user is on. For example, we created an array of widths for the Bootstrap cards:

widthArray = ['30rem', '50rem', '30rem', '70rem', '20rem', '60rem']

We were then able to dynamically style the cards based on the current page:

<Card style={{width: `${this.widthArray[this.state.currentQuestion.questionNumber - 1]}`}}>

3.) State also contains an array of user answer choices (“g”, “r”, “s”, “h”), with the letters denoting the four different Hogwarts houses.

In the backend, each answer choice had a table column for “house,” which would contain the aforementioned house abbreviations. This attribute was stored in the frontend array as the user selected different answers. For example, if the user selected three answer choices for Ravenclaw, two for Gryffindor, and one for Slytherin, the array might look like [“r,” “g”, “g”, “r”, “r”, “s”].

We then wrote a function that would then calculate the most frequent type of house in the answer choices:

findHouse = () => {
let answers = this.state.answeredQuestions.values;

//Create frequency hash that counts the number of each answer
let hash = {}; answers.forEach((answer) => { if (hash[answer]) {
hash[answer] += 1;
} else {
hash[answer] = 1;
}
});

// Calculate the house with the most answers
let mostFrequent = Object.keys(hash).reduce((a, b) => (hash[a] > hash[b] ? a : b)); this.props.finishQuiz(mostFrequent);};

When the house was calculated, then the user’s house would be sent as a PATCH request to the backend to edit the “house” column in the user table. Also, the user’s house would also be stored in state. The house result page renders the house conditionally based on the updated state.

By building this feature, my partner and I gained experience working with state to render different “pages” for questions and building an algorithm that calculated a Hogwarts house based on the user’s answer choices. I look forward to learning more about constructing algorithms to create a dynamic user experience.

--

--