Общий формат теста:
Я работаю над приложением для викторины, которое имеет три отдельных компонента, которые отображают то, что видит пользователь - «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;