Build Multiple Choice Quiz in React Native
Tags: javascript, reactnative
Published: 2019-12-02 09:47:46

This article is relevant to React Native!! If you are using React, you might find some state logic useful, but the components can not be transferred. 

**React Native Elements** has a component called **CheckBox** which is a great base for a list, but it needs a little hacking to get it to interact like a multiple choice quiz. 


>CheckBoxes allow users to complete tasks that involve making choices such as selecting options, or switching settings on or off. It provides a clear visual of either a true or false choice.

Since I couldn't find a native quiz component so I thought this would do the trick. I wanted a user to be able to click on a checkbox, or 'answer' and have a visual indicator change. The user would only be able to select one checkbox at a time though. 

I couldn't find an example of using CheckBox this way online that actually worked - I'm sure its probably out there - so here is how I customized it to become a simple dynamically rendering quiz component. 

![Imgur](https://i.imgur.com/nyJKxYW.gif)

####Getting Started####
To use the CheckBox, download the react-native-elements dependency 
with your preferred package manager. 

Then import it into the top of your component like so. 

```javascript
import { CheckBox } from 'react-native-elements'
```
The most simple implementation of CheckBox is below, but there are many props available to add to it. 

```javascript
<CheckBox
  title='Click Here'
  checked={this.state.checked}
/>
```
Adding an **onPress** prop  to CheckBox allows a function to toggle the state of 'checked' between true and false. 
 
```javascript
<CheckBox
  title='Click Here'
  checked={this.state.checked}
  onPress={() => this.setState({checked: !this.state.checked})}
/>
```
####The Problem
That's cool, but what happens when I want to have multiple checkboxes to display the answer choices?

As is, the checked state of all of them will be effected and toggled to all true or all false. 

I went ahead and added some more props with explanations.


```javascript
<View>
  <Text style={styles.question}>{question}</Text>
    <View>
      {answers.map((answer) => (
        <CheckBox
          center
          key={answer.id}
          title={answer.choice}
          // if these are not empty strings, the default checkbox appears
          checkedIcon=""
          uncheckedIcon=""
          checked={this.state[answer.id] || false}
          // ternary conditionally renders the color of choice container 
          containerStyle={this.state[answer.id]
          ? { backgroundColor: answer.isCorrect
              ? 'lightgreen' : 'pink' } : null}
          onPress={() => this.handleSelection(answer)}
         />
        ))}
    </View>
</View>
``` 

####Selection State Solution####

I asked 2 questions in **handleSelection**:
  * has any answer been selected before?
  * if so, is it the same answer or a new answer?

A good 'ole shuffle toy problem came to mind. I needed a variable to keep track of the previous selection to compare it to the current selection. Then, I'd set variable to the current value for the next comparison.

The magic happened in **dynamically setting and referencing the state**, seen as this.setState({[answer.id]: true}).

```javascript
 handleSelection(answer) {
    const { isSelected, prevChoice } = this.state;

    // has any answer been selected before?
    if (isSelected === false) {
      // if not, we set all state to current answer variables
      this.setState({
        isSelected: true,
        [answer.id]: true,
        prevChoice: answer.id,
      });
    } else {
      // A choice is already selected
      // If it is the same choice,
      prevChoice === answer.id
        ? this.setState({
          //  toggle off
          isSelected: false
          //  assign state of answer to false
          [answer.id]: false,
          //  reset the prev choice
          prevChoice: null,
        })
        // else we know it is a new choice,
        // we dont change state of 'isSelected'
        // set the previous to current
        : this.setState({
          // assign state at previous value false
          [prevChoice]: false,
          [answer.id]: true,
          // assign new id as prev
          prevChoice: answer.id,
        });
    }
  }
```

I really enjoyed figuring out this solution! I'm sure there are many other ways. :)