I just finished up writing a simplistic/trivial framework using ReactJS using which one could quickly create online quizzes. The code for this could be found on github on following page named as ReactJS-Quiz. I would like to take this opportunity to share AngularJS-Quiz that I wrote sometime back. I must say that I found writing quiz framework using ReactJS more fulfilling as it got aligned to my OOP oriented thinking and I was not required to envisage templates etc as in case of AngularJS. That said, both frameworks are cool and have their own pluses and minuses. Please feel free to suggest if I missed on mentioning one or more key aspects. Also, sorry for typos.
I shall be presenting some of the following key concepts of ReactJS while explaining the functionality of Quiz framework.
To make use of this framework, all that is required to be done is define JSON data model (or retrieve from server) as shown later in this article and that is it! In this blog, I will explain the design aspect of UI using ReactJS. Before that, let me quickly define this Quiz framework. Following are some of the features of first version of this quiz framework:
As a starter, I would recommend you to quickly read the ReactJS page on thinking in terms of components. Briefly speaking, when designing UI, one has to do following:
When designing UI for tests/quiz, following are some of key components as shown above:
The relationship between the components depicted below represents following:
React is all about modular, composable components.
var test = {
name: "Sample Test",
description: "This is a sample test paper to demonstrate the ReactJS UI design by components.",
passCutoff: 0.33,
applyNegativeMarking: false,
questions: [
{
id: "1",
qtext:"California is in which part of USA?",
options:[
{text:"East"},
{text:"Mid"},
{text:"West"},
{text:"South"}
],
ans:"West",
marks: 3
},
{
id: "2",
qtext:"Who is Prime Minister of India?",
options:[
{text:"Sonia Gandhi"},
{text:"Narendra Modi"},
{text:"Manmohan Singh"},
{text:"Rahul Gandhi"}
],
ans:"Narendra Modi",
marks: 2
},
{
id: "3",
qtext:"Which of the following is most popular Search Engine Company?",
options:[
{text:"Microsoft"},
{text:"Facebook"},
{text:"Google"},
{text:"Yahoo"}
],
ans:"Google",
marks: 1
},
]
};
In the above JSON data model, you would find “test” consisting of an array of questions which is modeled using “QuestionPaper” consisting of a list of “Question”s.
var Test = React.createClass({
getInitialState: function() {
return {totalscore : 0, testSubmitted: false};
},
handleChange: function(result) {
this.setState({totalscore: result.totalscore, testSubmitted: true});
},
render: function(){
var totalmarks = 0;
this.props.details.questions.map(function(question){
totalmarks += question.marks;
});
return(
<div>
<h1>{this.props.details.name}</h1>
<hr className="divider"/>
<div>{this.props.details.description}</div>
<table className="table">
<tr>
<td className="col-md-9">
<QuestionPaper questions={this.props.details.questions} applyNegativeMarking={this.props.details.applyNegativeMarking}
onSubmitted={this.handleChange}/>
</td>
<td className="col-md-3">
<Scorecard score={this.state.totalscore} testSubmitted={this.state.testSubmitted} percentage={Math.round(this.state.totalscore*100/totalmarks)}/>
</td>
</tr>
</table>
</div>
);
}
});
var QuestionPaper = React.createClass({
getInitialState: function() {
return {totalscore : 0};
},
handleChange: function(score) {
this.setState({totalscore: this.state.totalscore + score});
},
handleSubmitted: function(event) {
var result = {totalscore: this.state.totalscore};
this.props.onSubmitted( result );
},
render: function(){
var questionAnswers = this.props.questions.map(function(question){
return(
<tr><td><Question question={question.qtext} number={question.no} options={question.options} answer={question.ans} marks={question.marks} applyNegativeMarking={this.props.applyNegativeMarking} onAnswered={this.handleChange}/></td></tr>
);
}, this);
return(
<div>
<table className="table table-striped">{questionAnswers}</table>
<div><input type="button" className="btn btn-primary" value="Submit" onClick={this.handleSubmitted}/></div>
</div>
);
}
});
var Question = React.createClass({
getInitialState: function() {
return {
correctAnswerRecorded: false,
negativeAnswerRecorded: false
};
},
handleChange: function(event) {
var score = 0;
if( event.target.value == this.props.answer) {
if( this.state.correctAnswerRecorded === false ) {
if( this.props.applyNegativeMarking === true && this.state.negativeAnswerRecorded === true ) {
score = 1 + this.props.marks;
} else {
score = this.props.marks;
}
}
this.state.correctAnswerRecorded = true;
this.state.negativeAnswerRecorded = false;
} else {
if( this.props.applyNegativeMarking === true && this.state.negativeAnswerRecorded === false ) {
if( this.state.correctAnswerRecorded === true ) {
score = -1 - this.props.marks;
} else {
score = -1;
}
} else {
if( this.state.correctAnswerRecorded === true ) {
score = -this.props.marks;
}
}
this.state.negativeAnswerRecorded = true;
this.state.correctAnswerRecorded = false;
}
this.props.onAnswered(score);
},
render: function(){
var qname = "option" + this.props.number;
var qoptions = this.props.options.map(function(option){
return (
<div><input type="radio" name={qname} value={option.text} onChange={this.handleChange}/> {option.text}</div>
);
}, this);
return(
<div>
<div><strong>Q</strong>: {this.props.question}</div>
<div>{qoptions}</div>
<br/>
</div>
);
}
});
var Scorecard = React.createClass({
render: function(){
var status = "Test not submitted!";
if( this.props.testSubmitted == true ) {
if( this.props.percentage < 33 ) {
status = "Sorry, you could not pass the test. Try again later!"
} else {
status = "Congratulations!! You passed the test.";
}
}
return(
<div className="list-group">
<div className="list-group-item active">Test Result</div>
<div className="list-group-item">Score: <strong>{this.props.score}</strong></div>
<div className="list-group-item">Percentage: <strong>{this.props.percentage} %</strong></div>
<div className="list-group-item">Status: <strong>{status}</strong></div>
</div>
);
}
});
Please feel free to share any comments/suggestions that you may have. I would extend this framework with other features soon.
Large language models (LLMs) have fundamentally transformed our digital landscape, powering everything from chatbots and…
As Large Language Models (LLMs) evolve into autonomous agents, understanding agentic workflow design patterns has…
In today's data-driven business landscape, organizations are constantly seeking ways to harness the power of…
In this blog, you would get to know the essential mathematical topics you need to…
This blog represents a list of questions you can ask when thinking like a product…
AI agents are autonomous systems combining three core components: a reasoning engine (powered by LLM),…