Мой экран результатов приложения React Quiz не отображается - Есть идеи? - PullRequest
0 голосов
/ 25 апреля 2020

Общий формат теста:

Я работаю над приложением для викторины, которое имеет три отдельных компонента, которые отображают то, что видит пользователь - «StartScreen», «QuestionsScreen», и «EndScreen». По какой-то причине EndScreen не будет отображаться в соответствии с критериями, которые я ему предоставляю.

Все различные Компоненты перемещаются через компонент Quiz3, который содержит основные состояния для викторины, которые затем передаются в качестве реквизита для остальных трех. Основными состояниями, которые используются для определения того, на каком этапе теста находится пользователь, являются состояния «clickBegin» и «scoredQuiz». Они работают нормально, потому что я могу легко перемещаться по StartScreen и QuestionsScreen. Я предполагаю, что фактическая оценка теста - это то, где система разваливается.

Scoring Logi c:

Когда пользователь отвечает на все вопросы, найденные в объекте 'questions' в файле javascript -quiz-3. js, их ответы (которые обозначаются значением 'type', найденным под текстом определенный выбор) итерируются в массив, который изменяет значение состояния для показателя (находится в функциях functionA-D в основном файле). Эта часть работает нормально, и массив заполняется должным образом.

Когда на все вопросы даны ответы на 8 вопросов, и у нас есть полный массив результатов, функции A-D (в зависимости от того, какой ответ нажал) запускают Функция ScoreQuiz (). Эта функция обновляет значение состояния scoredQuiz до true и вычисляет наиболее частое значение, найденное в массиве оценок. Я делаю это с помощью для l oop с переменной сравнения, которая обновляется в зависимости от того, сколько раз найдена определенная строка. Когда найдена наиболее часто встречающаяся строка, для переменной сравнения устанавливается переменная mostFrequentValue. Затем эта переменная устанавливает состояние MostFrequent.

То, что я ожидаю, и ошибка:

Гипотетически, в зависимости от того, какое значение состояния «MostFrequent» заканчивается, предполагается, что он будет давать другой результат в компоненте EndScreen, где «MostFrequent» передается как реквизит. Логика c все выглядит нормально, но когда я запускаю тест, я получаю сообщение об ошибке:

"Uncaught Error: EndScreen (...): ничего не было возвращено из рендера. Это обычно означает, что оператор return отсутствует. Или, чтобы ничего не визуализировать, верните null. "

Все мои рендеры и возвраты настроены правильно, поэтому я не знаю, что обнаруживает React. Какие-нибудь мысли?

Фактический код:

викторина-3. js:

import React from 'react'; 
import TopNavbar from '../navbar';
import {startLabels} from './javascript/javascript-quiz-3'; 
import {questions} from './javascript/javascript-quiz-3';
import {endLabels} from './javascript/javascript-quiz-3'; 
import {Container} from 'react-bootstrap'; 
import {Row} from 'react-bootstrap';
import {Col} from 'react-bootstrap';

export default class Quiz3 extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      clickBegin: false,
      scoredQuiz: false,
      currentQuestion: 0,
      score: [],
      mostFrequent: '',
    }
    this.reset = this.reset.bind(this); 
    this.changeClicked = this.changeClicked.bind(this); 
    this.scoreQuiz = this.scoreQuiz.bind(this); 
    this.functionA = this.functionA.bind(this);
    this.functionB = this.functionB.bind(this);
    this.functionC = this.functionC.bind(this);
    this.functionD = this.functionD.bind(this); 
  }

  // State Functions

  reset() {
    this.setState({
      currentQuestion: 0,
      score: [],
    })
  }

  changeClicked() {
    if (this.state.clickBegin === false) {
      this.setState({
        clickBegin: true
      })
    }
    else {
      this.setState({
        clickBegin: false
      })
    console.log(this.state.clickBegin)
    }
  }

  scoreQuiz() {
      this.setState({
        scoredQuiz: true
      })
      for(var i = 0; i > this.state.score.length; i++) {
        var counts = {}; 
        var compare = 0; 
        var result = this.state.score[i];
        var mostFrequentValue = undefined;

        if (counts[result] === undefined) {
          counts[result] = 1
        }
        else {
          counts[result] = counts[result] + 1
        }

        if (counts[result] > compare) {
          compare = counts[result]; 
          mostFrequentValue = this.state.score[i]; 
        }
      }
      this.setState({
        mostFrequent: mostFrequentValue
      })
  }

  functionA () {
    if(this.state.currentQuestion < 7) {
      this.setState ({
        score: [...this.state.score, questions[this.state.currentQuestion].choiceA.type], 
        currentQuestion: this.state.currentQuestion + 1
      })
    }
    else if(this.state.currentQuestion >= 7) {
      this.scoreQuiz(); 
    }
    return;
  }

  functionB () {
    if(this.state.currentQuestion < 7) {
      this.setState ({
        score: [...this.state.score, questions[this.state.currentQuestion].choiceB.type], 
        currentQuestion: this.state.currentQuestion + 1
      })
    }
    else if(this.state.currentQuestion >= 7) {
      this.scoreQuiz(); 
    }
    return;
  }

  functionC () {
    if(this.state.currentQuestion < 7) {
      this.setState ({
        score: [...this.state.score, questions[this.state.currentQuestion].choiceC.type], 
        currentQuestion: this.state.currentQuestion + 1
      })
    }
    else if(this.state.currentQuestion >= 7) {
      this.scoreQuiz(); 
    }
    return;
  }

  functionD () {
    if(this.state.currentQuestion < 7) {
      this.setState ({
        score: [...this.state.score, questions[this.state.currentQuestion].choiceD.type], 
        currentQuestion: this.state.currentQuestion + 1
      })
    }
    else if(this.state.currentQuestion >= 7) {
      this.scoreQuiz(); 
    }
    return;
  }

// Different pages rendered depending on state values

  render() {
    if (this.state.clickBegin === false && this.state.scoredQuiz === false) {
      return (
        <div>
          <TopNavbar />
          <div id = "main">
            <StartScreen 
            clickBegin = {this.state.clickBegin}
            scoredQuiz = {this.state.scoredQuiz}
            currentQuestion = {this.state.currentQuestion}
            score = {this.state.score}
            changeClicked = {this.changeClicked} 
            reset = {this.reset} />
          </div>
        </div>
      )
    }
    if (this.state.clickBegin === true && this.state.scoredQuiz === false) {
      return (
        <div id = "main">
          <TopNavbar />
          <QuestionsScreen 
            clickBegin = {this.state.clickBegin}
            scoredQuiz = {this.state.scoredQuiz}
            currentQuestion = {this.state.currentQuestion} 
            score = {this.state.score}
            functionA = {this.functionA}
            functionB = {this.functionB}
            functionC = {this.functionC}
            functionD = {this.functionD} />
        </div>
      )
    }

    if (this.state.clickBegin === true && this.state.scoredQuiz === true) {
      return (
        <div>
          <TopNavbar />
            <EndScreen 
              currentQuestion = {this.state.currentQuestion}
              score = {this.state.score}
              mostFrequent = {this.state.mostFrequent}
              scoreQuiz = {this.scoreQuiz} 
              reset = {this.reset}
            />
        </div>
      )
    }
    else {
      return null;
    }
  }
}

class StartScreen extends React.Component {
  constructor(props) {
    super(props)
    this.click = this.click.bind(this);
  }
  click() {
    this.props.changeClicked();
    this.props.reset(); 
  }
  render() {
    return (
      <Container fluid id = 'start-screen'>
        <Row id = "quiz-title"> 
          <h1> {startLabels[0].title} </h1> 
        </Row>
        <Row>
          <img src = {startLabels[0].imgSrc} /> 
        </Row>
        <Row id = "quiz-description"> 
          <p> {startLabels[0].descrip} </p> 
        </Row>
        <Row id = "begin-quiz" onClick = {this.click}> 
          <p> {startLabels[0].startQuiz} </p> 
        </Row> 
      </Container>
    )
  }
}

class QuestionsScreen extends React.Component {
  render() {
    return (
      <Container fluid id = "questions-screen"> 
        <Row id = "question-title"> 
          <p> {questions[this.props.currentQuestion].question} </p> 
        </Row>
        <Row id = "choice-container-1"> 
          <Col id = "choiceA" onClick = {this.props.functionA}> <p> {questions[this.props.currentQuestion].choiceA.choice} </p> </Col>
          <Col id = "choiceB" onClick = {this.props.functionB}> <p> {questions[this.props.currentQuestion].choiceB.choice} </p> </Col>
        </Row>
        <Row id = "choice-container-2">
          <Col id = "choiceC" onClick = {this.props.functionC}> <p> {questions[this.props.currentQuestion].choiceC.choice} </p> </Col>
          <Col id = "choiceD" onClick = {this.props.functionD}> <p> {questions[this.props.currentQuestion].choiceD.choice} </p> </Col>
        </Row>
      </Container>
    )
  }
}

class EndScreen extends React.Component {
  render() {
    if (this.props.mostFrequent === "Warrior") {
      return (
        <Container fluid id = "end-screen"> 
          <Row id = "result"> <h1> {endLabels[0].result} </h1> </Row>
          <Row id = "result-picture"> <img src = {endLabels[0].imgSrc} /> </Row>
          <Row id = "result-description"> <p> {endLabels[0].descrip} </p> </Row>
          <Row id = "take-again" onclick = {this.props.reset}> <p> {endLabels[0].takeAgain} </p> </Row>
        </Container>
      )
    }
    if (this.props.mostFrequent === "Rogue") {
      return (
        <Container fluid id = "end-screen"> 
          <Row id = "result"> <h1> {endLabels[1].result} </h1> </Row>
          <Row id = "result-picture"> <img src = {endLabels[1].imgSrc} /> </Row>
          <Row id = "result-description"> <p> {endLabels[1].descrip} </p> </Row>
          <Row id = "take-again" onclick = {this.props.reset}> <p> {endLabels[1].takeAgain} </p> </Row>
        </Container>
      )
    }
    if (this.props.mostFrequent === "Sorcerer") {
      return (
        <Container fluid id = "end-screen"> 
          <Row id = "result"> <h1> {endLabels[2].result} </h1> </Row>
          <Row id = "result-picture"> <img src = {endLabels[2].imgSrc} /> </Row>
          <Row id = "result-description"> <p> {endLabels[2].descrip} </p> </Row>
          <Row id = "take-again" onclick = {this.props.reset}> <p> {endLabels[2].takeAgain} </p> </Row>
        </Container>
      )
    }
    if (this.props.mostFrequent === "Bard") {
      return (
        <Container fluid id = "end-screen"> 
          <Row id = "result"> <h1> {endLabels[3].result} </h1> </Row>
          <Row id = "result-picture"> <img src = {endLabels[3].imgSrc} /> </Row>
          <Row id = "result-description"> <p> {endLabels[3].descrip} </p> </Row>
          <Row id = "take-again" onclick = {this.props.reset}> <p> {endLabels[3].takeAgain} </p> </Row>
        </Container>
      )
    }
  }
}

викторина-3- javascript. js:

// HTML fill-in for each part of quiz //

export const startLabels = [
  {
    title: "Which RPG class are you?",
    imgSrc: "",
    descrip: "Pick the lock, or break the face?",
    startQuiz: "Start Quiz!",
  },
];

export const questions = [

  {
    question: "Pick your weapon!",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "A stick I found on the ground.",
      type: 'Warrior',
    },
    choiceB: {
       choice: "I'll just steal if off someone.",
       type: 'Rogue',
    },
    choiceC: {
       choice: "Green stuff shooting out of my hands.",
       type: 'Sorcerer',
    },
    choiceD: {
       choice: "My silver tongue.",
       type: 'Bard',
   },
  }, 

  {
   question: "There's an orc guarding the chest you need to get to. Do you...",
   imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
   choiceA: {
     choice: "Throw a rock to distract him and sneak in.",
     type: 'Rogue',
   },
   choiceB: {
      choice: "Smash their face in. And then the chest.",
      type: 'Warrior',
   },
   choiceC: {
      choice: "Convice the orc that you are their chief.",
      type: 'Bard',
   },
   choiceD: {
      choice: "Teleport the chest to you.",
      type: 'Sorcerer',
    },
  }, 

  {
    question: "There's a strange mist washign over you. How do you respond?",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "Perceive what type of magic it is.",
      type: 'Sorcerer',
    },
    choiceB: {
       choice: "Use the mist to hide.",
       type: 'Rogue',
    },
    choiceC: {
       choice: "Ready your weapon and know you're going to use it.",
       type: 'Warrior',
    },
    choiceD: {
       choice: "Find the mist melancholic and beautiful. Get song ideas.",
       type: 'Bard',
   },
  }, 

   {
    question: "You think you got a bad deal from a shopkeeper on a ring you sold. Do you... ?",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "Sneak back in when the shop is closed and take the ring.",
      type: 'Rogue',
    },
    choiceB: {
       choice: "Threaten the shop owner and note how you can smash their counter.",
       type: 'Warrior'
    },
    choiceC: {
       choice: "Cast an illusion in the shop that absorbs all metal objects in the shop until the ring is returned.",
       type: 'Sorcerer'
    },
    choiceD: {
       choice: "Charm the shopkeeper so they give you the ring back.",
       type: 'Bard',
   },
  }, 

  {
    question: "You get ambushed on the way to the city. You are clearly outnumbered.",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "They may have numbers, but I have my axe.",
      type: 'Warrior',
    },
    choiceB: {
       choice: "Throw a smokebomb down and run to higher ground.",
       type: 'Rogue',
    },
    choiceC: {
       choice: "Create a ring of fire around you.",
       type: 'Sorcerer',
    },
    choiceD: {
       choice: "Play the ambush a song. Leave unaffected.",
       type: 'Bard',
   },
  }, 

  {
    question: "What does your ideal world look like?",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "Everyone takes the time to learn.",
      type: 'Sorcerer'
    },
    choiceB: {
       choice: "Everyone would be honest and direct.",
       type: 'Warrior',
    },
    choiceC: {
       choice: "Endless beauty.",
       type: 'Bard',
    },
    choiceD: {
       choice: "Deeper pockets.",
       type: 'Rogue',
   },
  }, 

  {
    question: "The front door is locked. What do you do?",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "Pick the lock of course!",
      type: 'Rogue',
    },
    choiceB: {
       choice: "Melt the lock.",
       type: 'Sorcerer',
    },
    choiceC: {
       choice: "It just needs more force!",
       type: 'Warrior',
    },
    choiceD: {
       choice: "Maybe find the key?",
       type: 'Bard',
   },
  }, 

  {
    question: "Your quest is done. What do you do to unwind?",
    imgSrc: "https://a.wattpad.com/cover/140215314-352-k843958.jpg",
    choiceA: {
      choice: "Flirt with the most beautiful people I can find.",
      type: 'Bard',
    },
    choiceB: {
       choice: "Explore the realm of each element.",
       type: 'Sorcerer',
    },
    choiceC: {
       choice: "Eat as much as I can!",
       type: 'Warrior',
    },
    choiceD: {
       choice: "Find a quiet corner to relax with my treasures.",
       type: 'Rogue',
   },
  },
];

export const endLabels = [
  {
  result: "Warrior",
  imgSrc: "",
  descrip: "No problem can't be solved with my axe.",
  takeAgain: "Take Again!"
  }, 


  {
  result: "Rogue",
  imgSrc: "",
  descrip: "The shadows are my natural home.",
  takeAgain: "Take Again!"
  }, 


  {
  result: "Sorcerer",
  imgSrc: "",
  descrip: "Life, to you, is a world of mysteries to be uncovered.",
  takeAgain: "Take Again!"
  }, 


  {
  result: "Bard",
  imgSrc: "",
  descrip: "The world is boring without a little beauty.",
  takeAgain: "Take Again!"
  }, 

];

navbar. js:

import React from 'react'; 
import {Navbar} from 'react-bootstrap'; 
import {Container} from 'react-bootstrap'; 
import {NavDropdown} from 'react-bootstrap'; 
import {Button} from 'react-bootstrap'; 
import {Link} from 'react-router-dom'; 

class TopNavbar extends React.Component {
    render() {
        return (
            <div>
                <Navbar expand = 'lg' bg = 'light' variant = 'light'>
                <Container fluid>
                    <NavDropdown title = "|||" id = "basic-nav-dropdown">
                        <NavDropdown.Item> <Link to = "/"> Quizzes </Link> </NavDropdown.Item> 
                        <NavDropdown.Item> <Link to = "/register"> Register </Link> </NavDropdown.Item> 
                        <NavDropdown.Item> <Link to = "/subscribe"> Subscribe </Link> </NavDropdown.Item> 
                    </NavDropdown>
                    <Link to = "/"> <img alt = 'placeholder'/> </Link>
                    <Link to = "/login"> <Button className = "login"> Login </Button></Link>
                </Container>
                </Navbar>
            </div>
        )
    }
} 

export default TopNavbar; 
...