1
\$\begingroup\$

I'm trying to build a multiple-choice quiz using ReactJS. When the Submit button is clicked, I want to give immediate feedback by changing the text 'input' color (green/red). Right now, it feels like I'm duplicating code in the handleSubmit and render sections.

Is there a better way to pass classType? Also, what's the best way to move to next question other than using the additional current variable and using quiz[ this.state.current + 1 ]?

Any comments on improving/organizing this code will be appreciated.

jsfiddle

var quiz = [{
    "question": "What does CSS stand for?",
    "choices": ["Creative Style Sheets", "Computer Style Sheets", "Cascading Style Sheets"],
    "answer": "Cascading Style Sheets"
}, {
    "question": "Which CSS property controls the text size?",
    "choices": ["text-size", "font-size", "font-style"],
    "answer": "font-size"
}, {
    "question": "What does HTML stand for?",
    "choices": ["Hyperlinks and Text Markup Language", "Hyper Text Markup Language", "Home Tool Markup Language"],
    "answer": "Hyper Text Markup Language"
}];

var QuizContainer = React.createClass( {
    getInitialState: function() {
        return {
            current: 0,
            current_quiz: quiz[ 0 ],
            user_choice: "",
            score: 0,
            verifying_answer: false
        };
    },
    selectedAnswer: function( option ) {
        this.setState( { user_choice: option } );
    },
    handleSubmit: function() {
            if ( !this.state.verifying_answer ) {
                if ( this.state.current_quiz.answer === this.state.user_choice ) {
                    this.setState( {
                        score: this.state.score + 1,
                    } );
                }
                this.setState( { verifying_answer: true } );
            } else {
                if ( this.state.current < quiz.length -1 ) {
                    this.setState( {
                        current_quiz: quiz[ this.state.current + 1 ],
                        current: this.state.current + 1,
                        verifying_answer: false,
                        user_choice: ""
                    } );
                }
            }
        },
    render: function() {
        var self = this;
        var choices = this.state.current_quiz.choices.map( function( choice, index ) {
            var classType  = "";
            if ( self.state.verifying_answer ) {
                if ( choice === self.state.current_quiz.answer ) {
                    classType = "text-success";
                } else if ( choice === self.state.user_choice && self.state.user_choice !== self.state.current_quiz.answer ) {
                    classType = "text-danger";
                }
            }
            return (
                <RadioInput key={choice} choice={choice} index={index} onChoiceSelect={self.selectedAnswer} disable={self.state.verifying_answer} classType={classType}/>
            );
        } );
        var button_name = !this.state.verifying_answer ? "Submit" : "Next Question";
        return(
            <div className="quizContainer">
                <h1>Quiz</h1>
                <p>{this.state.current_quiz.question}</p>
                {choices}
                <button id="submit" className="btn btn-default" onClick={this.handleSubmit}>{button_name}</button>
                <ScoreBox score={this.state.score} />
            </div>
        );
    }
} );

var RadioInput = React.createClass( {
    handleClick: function() {
        this.props.onChoiceSelect( this.props.choice );
    },
    render: function() {
        var disable = this.props.disable;
        var classString = !disable ?  "radio" :  "radio disabled";
        return (
            <div className={classString}>
                <label className={this.props.classType}>
                    <input type="radio" name="optionsRadios" id={this.props.index} value={this.props.choice} onChange={this.handleClick} disabled={disable} />
                    {this.props.choice}
                </label>
            </div>
        );
    }
} );

var ScoreBox = React.createClass( {
    render: function() {
        return (
            <div className="score">
                <p>Score: {this.props.score} right answers out of {quiz.length} possible.</p>
            </div>
        );
    }
} );

React.render(
    <QuizContainer />,
    document.body
);
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.