Skip to main content

Quiz App - deel 2

We zijn bezig met het maken van een Quiz app te maken in REACT. Dit is deel twee waarin we onze App verder gaan afmaken. We leren hier ook een nieuwe techniek waarmee we in JSX door een array heen kunnen loopen.

Daarnaast gaan we met de Ternary oparatore een soort if-then-else maken in JSX.

Zorg ervoor dat je Quiz App - deel 1 goed hebt doorlopen en dat alles goed werkt.

Stap 1 - een loop in JSX met de map functie

Onze render methode in de class App ziet er tot nu toe zo uit:

render() {
  var antwoorden=questions[this.state.vraagNr].answerOptions;
  return (
    <div className="app">
        <div>{questions[this.state.vraagNr].questionText}</div>
        <button onClick={() => this.handleAnswerOptionClick(antwoorden[0].isCorrect)}>{antwoorden[0].answerText}</button>
        <button onClick={() => this.handleAnswerOptionClick(antwoorden[1].isCorrect)}>{antwoorden[1].answerText} {antwoorden[1].isCorrect}</button>
        <button onClick={() => this.handleAnswerOptionClick(antwoorden[2].isCorrect)}>{antwoorden[2].answerText} {antwoorden[2].isCorrect}</button>
        <button onClick={() => this.handleAnswerOptionClick(antwoorden[3].isCorrect)}>{antwoorden[3].answerText} {antwoorden[3].isCorrect}</button>
    </div>
  );
}

Regel 6,7, 8 en 9 lijken erg veel op elkaar en kunne in een loop worden geplaatst. De code is JSX (uitleg zie eerste les) en binnen JSX maken we een loop met de map functie. Lees hiervoor de uitleg op:

https://www.telerik.com/blogs/beginners-guide-loops-in-react-jsx

Lees de uitleg goed en vervang de vier regels dan door de volgende code:

{ antwoorden.map((antwoord) => (
  <button onClick={() => this.handleAnswerOptionClick(antwoord.isCorrect)}>{antwoord.answerText} {antwoord.isCorrect}</button>
))}

Je loopt dus door het array antwoorden heen en het element komt telkens in antwoord. Dus de eerste keer in de loop geldt:

antwoord = antwoorden[0]

daarna wordt

antwoord = atwoorden[1]

antwoord = antwoorden[2]

etc.

Stap 2 - Voortgang (vraagnummer)

In de state variabele vraagNr houden we bij bij welke vraag we zijn. Deze telt vanaf 0. We zin dus bij vraag vraagNr+1 en we hebben in totaal questions.length vragen. Dat hadden we in onze vorige les al gebruikt om te bepalen of we al bij de laatste vraag waren.

We willen op de regels afdrukken "Vraag X van Y. X is dus de state variabale vraagNr en y is de lengte van het questionsArray. We maken een aparte div zodat we de tekst straks apart kunnen stijlen.

<div>
  Vraag {this.state.vraagNr + 1} van {questions.length}
</div>

Plaats deze JSX code zodat deze regel boven aan wordt geplaatst.

Stap 3 - CSS stijlen

We maken gebruik van flex boxen; we maken één rij met twee colummen. De hele app is één rij dus de volgende code kan bij de CSS-stijl .app worden geplaatst.

display: flex;
flex-direction: row;
justify-content: space-evenly;

We maken de twee kolommen voeg de volgende class toe in de CSS file:

.column {
  width: 100%;
  display: flex;
  flex-direction: column;
  flex: 1;
}

We maken nu de volgende structuur.

<div className="app">

  <div className="column">
    <span>Vraag {this.state.vraagNr + 1} van {questions.length}</span>
    <span className="question">{questions[this.state.vraagNr].questionText}</span>
  </div>

  <div className="column">
    { antwoorden.map((antwoord) => (
      <button onClick={() => this.handleAnswerOptionClick(antwoord.isCorrect)}>{antwoord.answerText} {antwoord.isCorrect}</button>
    ))}
  </div>

</div>

Als je je code test dan zie je dat de knoppen aan de rechterkant niet mooi zijn uitgelijnd. Maak een nieuw class.

.uitlijnen {
  justify-content: space-between;
}

En zet deze class bij de tweede kolom.

 <div className="column uitlijnen">

De buttons stijlen we als volgt (plaats de code in de app.css file.

button {
  width: 100%;
  font-size: 16px;
  color: #ffffff;
  background-color: #252d4a;
  border-radius: 15px;
  display: flex;
  padding: 5px;
  justify-content: flex-start;
  align-items: center;
  border: 5px solid #234668;
  cursor: pointer;
}

button:hover {
  background-color: #555e7d;
}

button:focus {
  outline: none;
}

De app is nu al bijna af!

De enige stap is nog dat we de score moeten bijhouden en aan het eind moeten stoppen en de score laten zien.

Stap 4, Score

We hadden al een score state variabele gemaakt. We hoeven alleen nog maar een punt bij de score op te tellen als de vraag goed is beantwoord. We weten ook al wanneer een vraag goed is beantwoord want daar hebben we nog een console.log staan.

Achter de console.log waar we afdrukken dat het antwoord goed is plaatsen we dus de volgende code.

this.setState( {'score': this.state.score+1} );

Stap 5, het einde

Als de vraagNr (this.state.vraagNr) 4 is dan zijn we in ons geval bij de laatste vraag. We gaan dan niet meer door naar de volgende vraag want we tellen alleen een bij de vraagNr op als de vraag < vraagNr -1.

Laten we er nog wel één bij op tellen en door tellen tot 5. Vraag 5 (eigenlijk vraag 6 want we beginnen bij 0 te tellen) bestaat niet meer. Laten we toch de if in de methode handleAnswerOptionClick veranderen en de -1 weglaten.

if ( this.state.vraagNr < questions.length ) {
  this.setState( {'score': this.state.score+1} );
}

We tellen nu dus één te ver door. Test maar we zullen een foutmelding krijgen.

We krijgen de foutmelding als

this.state.vraagnr === questions.length

In dat geval moeten we niet de volgende vraag laten zien, maar het eindresultaat, de score.

We gaan de Ternary operator gebruiken in onze JSX code.

De opzet wordt als volgt:

( einde ? laat einde zien : laat de vraag zien )