├── .babelrc ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── config └── eslint.js ├── package-lock.json ├── package.json ├── src ├── components │ ├── Answer.js │ ├── Modal.js │ ├── Question.js │ ├── QuestionList.js │ ├── Quiz.js │ ├── QuizApp.js │ └── Results.js ├── data │ └── quiz-data.js ├── helpers │ ├── shuffleQuestions.js │ └── tally.js ├── index.html ├── main.js └── style.css ├── webpack.config.dev.js └── webpack.config.prod.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "react", 5 | "stage-2" 6 | ], 7 | "plugins": [ 8 | "react-hot-loader/babel" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | const clientESLintConfig = require('./config/eslint'); 2 | 3 | module.exports = Object.assign({}, clientESLintConfig, { 4 | env: Object.assign({}, clientESLintConfig.env, { 5 | node: true, 6 | }) 7 | }); 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 David Ra Youssef 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Quiz 2 | A JavaScript slide quiz built with React. 3 | 4 | [View Demo](http://davidra.co/react-quiz/) 5 | 6 | Getting Started 7 | --------------- 8 | 9 | ```shell 10 | $ git clone https://github.com/davidrayoussef/react-quiz.git 11 | $ cd react-quiz 12 | $ npm install 13 | $ npm start 14 | ``` 15 | 16 | App Structure 17 | ------------- 18 | 19 | ``` 20 | QuizApp 21 | └── Quiz 22 | ├── QuestionList 23 | | └── Question 24 | | └── Answer 25 | └── Results 26 | ``` 27 | -------------------------------------------------------------------------------- /config/eslint.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2015-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found in the 6 | * LICENSE file in the root directory of this source tree. An additional grant 7 | * of patent rights can be found in the PATENTS file in the same directory. 8 | */ 9 | 10 | // Inspired by https://github.com/airbnb/javascript but less opinionated. 11 | 12 | // We use eslint-loader so even warnings are very visibile. 13 | // This is why we only use "WARNING" level for potential errors, 14 | // and we don't use "ERROR" level at all. 15 | 16 | // In the future, we might create a separate list of rules for production. 17 | // It would probably be more strict. 18 | 19 | module.exports = { 20 | root: true, 21 | 22 | parser: 'babel-eslint', 23 | 24 | plugins: ['react'], 25 | 26 | env: { 27 | browser: true, 28 | commonjs: true, 29 | es6: true, 30 | jest: true, 31 | node: true 32 | }, 33 | 34 | parserOptions: { 35 | ecmaVersion: 6, 36 | sourceType: 'module', 37 | ecmaFeatures: { 38 | jsx: true, 39 | generators: true, 40 | experimentalObjectRestSpread: true 41 | } 42 | }, 43 | 44 | extends: [ 45 | 'eslint:recommended', 46 | 'plugin:react/recommended' 47 | ], 48 | 49 | settings: { 50 | 'import/ignore': [ 51 | 'node_modules', 52 | '\\.(json|css|jpg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm)$', 53 | ], 54 | 'import/extensions': ['.js'], 55 | 'import/resolver': { 56 | node: { 57 | extensions: ['.js', '.json'] 58 | } 59 | } 60 | }, 61 | 62 | rules: { 63 | 'react/jsx-key': 'off', 64 | 'react/no-unescaped-entities': 'off', 65 | 66 | // http://eslint.org/docs/rules/ 67 | 'array-callback-return': 'warn', 68 | 'default-case': ['warn', { commentPattern: '^no default$' }], 69 | 'dot-location': ['warn', 'property'], 70 | 'eqeqeq': ['warn', 'allow-null'], 71 | 'guard-for-in': 'warn', 72 | 'new-parens': 'warn', 73 | 'no-array-constructor': 'warn', 74 | 'no-caller': 'warn', 75 | 'no-cond-assign': ['warn', 'always'], 76 | 'no-console': 'off', 77 | 'no-const-assign': 'warn', 78 | 'no-control-regex': 'warn', 79 | 'no-delete-var': 'warn', 80 | 'no-dupe-args': 'warn', 81 | 'no-dupe-class-members': 'warn', 82 | 'no-dupe-keys': 'warn', 83 | 'no-duplicate-case': 'warn', 84 | 'no-empty-character-class': 'warn', 85 | 'no-empty-pattern': 'warn', 86 | 'no-eval': 'warn', 87 | 'no-ex-assign': 'warn', 88 | 'no-extend-native': 'warn', 89 | 'no-extra-bind': 'warn', 90 | 'no-extra-label': 'warn', 91 | 'no-fallthrough': 'warn', 92 | 'no-func-assign': 'warn', 93 | 'no-implied-eval': 'warn', 94 | 'no-invalid-regexp': 'warn', 95 | 'no-iterator': 'warn', 96 | 'no-label-var': 'warn', 97 | 'no-labels': ['warn', { allowLoop: false, allowSwitch: false }], 98 | 'no-lone-blocks': 'warn', 99 | 'no-loop-func': 'warn', 100 | 'no-mixed-operators': ['warn', { 101 | groups: [ 102 | ['&', '|', '^', '~', '<<', '>>', '>>>'], 103 | ['==', '!=', '===', '!==', '>', '>=', '<', '<='], 104 | ['&&', '||'], 105 | ['in', 'instanceof'] 106 | ], 107 | allowSamePrecedence: false 108 | }], 109 | 'no-multi-str': 'warn', 110 | 'no-native-reassign': 'warn', 111 | 'no-negated-in-lhs': 'warn', 112 | 'no-new-func': 'warn', 113 | 'no-new-object': 'warn', 114 | 'no-new-symbol': 'warn', 115 | 'no-new-wrappers': 'warn', 116 | 'no-obj-calls': 'warn', 117 | 'no-octal': 'warn', 118 | 'no-octal-escape': 'warn', 119 | 'no-redeclare': 'warn', 120 | 'no-regex-spaces': 'warn', 121 | 'no-restricted-syntax': [ 122 | 'warn', 123 | 'LabeledStatement', 124 | 'WithStatement', 125 | ], 126 | 'no-return-assign': 'warn', 127 | 'no-script-url': 'warn', 128 | 'no-self-assign': 'warn', 129 | 'no-self-compare': 'warn', 130 | 'no-sequences': 'warn', 131 | 'no-shadow-restricted-names': 'warn', 132 | 'no-this-before-super': 'warn', 133 | 'no-sparse-arrays': 'warn', 134 | 'no-throw-literal': 'warn', 135 | 'no-undef': 'warn', 136 | 'no-unexpected-multiline': 'warn', 137 | 'no-unreachable': 'warn', 138 | 'no-unused-expressions': 'warn', 139 | 'no-unused-labels': 'warn', 140 | 'no-unused-vars': ['warn', { vars: 'local', args: 'none' }], 141 | 'no-use-before-define': ['warn', 'nofunc'], 142 | 'no-useless-computed-key': 'warn', 143 | 'no-useless-concat': 'warn', 144 | 'no-useless-constructor': 'warn', 145 | 'no-useless-escape': 'warn', 146 | 'no-useless-rename': ['warn', { 147 | ignoreDestructuring: false, 148 | ignoreImport: false, 149 | ignoreExport: false, 150 | }], 151 | 'no-with': 'warn', 152 | 'no-whitespace-before-property': 'warn', 153 | 'operator-assignment': ['warn', 'always'], 154 | radix: 'warn', 155 | 'require-yield': 'warn', 156 | 'rest-spread-spacing': ['warn', 'never'], 157 | strict: ['warn', 'never'], 158 | 'unicode-bom': ['warn', 'never'], 159 | 'use-isnan': 'warn', 160 | 'valid-typeof': 'warn', 161 | 162 | // https://github.com/yannickcr/eslint-plugin-react/tree/master/docs/rules 163 | 'react/jsx-equals-spacing': ['warn', 'never'], 164 | 'react/jsx-no-duplicate-props': ['warn', { ignoreCase: true }], 165 | 'react/jsx-no-undef': 'warn', 166 | 'react/jsx-pascal-case': ['warn', { 167 | allowAllCaps: true, 168 | ignore: [], 169 | }], 170 | 'react/jsx-uses-react': 'warn', 171 | 'react/jsx-uses-vars': 'warn', 172 | 'react/no-deprecated': 'warn', 173 | 'react/no-direct-mutation-state': 'warn', 174 | 'react/no-is-mounted': 'warn', 175 | 'react/react-in-jsx-scope': 'warn', 176 | 'react/require-render-return': 'warn' 177 | } 178 | }; 179 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-quiz", 3 | "version": "1.10.0", 4 | "description": "A JavaScript quiz built with React.", 5 | "main": "main.js", 6 | "scripts": { 7 | "start": "webpack-dev-server --mode development --config webpack.config.dev.js --open", 8 | "build": "webpack --mode production --config webpack.config.prod.js --progress" 9 | }, 10 | "repository": "davidrayoussef/react-quiz", 11 | "homepage": "https://github.com/davidrayoussef/react-quiz", 12 | "author": "David Ra Youssef (davidradeveloper@gmail.com)", 13 | "license": "MIT", 14 | "devDependencies": { 15 | "babel-core": "^6.26.0", 16 | "babel-eslint": "^8.2.3", 17 | "babel-loader": "^7.1.4", 18 | "babel-preset-env": "^1.6.1", 19 | "babel-preset-react": "^6.24.1", 20 | "babel-preset-stage-2": "^6.24.1", 21 | "css-loader": "^0.28.11", 22 | "eslint": "^4.19.1", 23 | "eslint-loader": "^2.0.0", 24 | "eslint-plugin-react": "^7.7.0", 25 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 26 | "html-webpack-plugin": "^3.2.0", 27 | "prop-types": "^15.6.1", 28 | "react": "^16.3.2", 29 | "react-dom": "^16.3.2", 30 | "react-hot-loader": "^4.1.1", 31 | "style-loader": "^0.21.0", 32 | "webpack": "^4.6.0", 33 | "webpack-cli": "^2.0.15", 34 | "webpack-dev-server": "^3.1.3" 35 | }, 36 | "keywords": [ 37 | "react", 38 | "quiz", 39 | "test", 40 | "react-component" 41 | ], 42 | "dependencies": {} 43 | } 44 | -------------------------------------------------------------------------------- /src/components/Answer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | const Answer = ({ answer, handleAnswerClick, handleEnterPress }) => { 5 | return ( 6 |
bind
, call
, or apply
methods?,
46 | answers: [
47 | You can use call
or apply
to borrow methods from other objects.,
48 | You can use bind
for partial function application.,
49 | If you're using the map
method to run a function on an array and you need to preserve the this
context, you can use bind
.,
50 | All of the above.
51 | ],
52 | correct: 3
53 | },
54 | {
55 | question: What does the bind
method do?,
56 | answers: [
57 | Returns a function that, when executed, will call the original function with a this
context that you pass in.,
58 | Prevents the value of this
from being overridden by call
or apply
.,
59 | Allows you to implement partial application of a function.,
60 | All of the above.
61 | ],
62 | correct: 3
63 | },
64 | {
65 | question: How do objects inherit methods in JavaScript?,
66 | answers: [
67 | With Object.create
or Object.setPrototypeOf
.,
68 | With class Sub extends Super
in ES2015.,
69 | Using Parent.prototype.method.call
inside Child.prototype.method
.,
70 | All of the above.
71 | ],
72 | correct: 3
73 | },
74 | {
75 | question: What is a promise?,
76 | answers: [
77 | An object that represents a possible future value.,
78 | An object that's used for deferred and asynchronous computations.,
79 | A proxy for a value that will eventually become available.,
80 | All of the above.
81 | ],
82 | correct: 3
83 | },
84 | {
85 | question: What is CORS?,
86 | answers: [
87 | Cross-Origin Resource Sharing,
88 | Allows restricted resources (e.g. fonts) on a web page to be requested from an outside domain.,
89 | Allows scripts to interact more openly with content outside of the original domain, leading to better integration between web services.,
90 | All of the above.
91 | ],
92 | correct: 3
93 | },
94 | {
95 | question: What is an Angular expression?,
96 | answers: [
97 | A JavaScript-like code snippet that is evaluated by Angular.,
98 | A code snippet that is evaluated in the context of the current model scope, rather than within the scope of the global context (window).,
99 | A binding in double curly brackets that gets evaluated and the results appear in the DOM in place of it.,
100 | All of the above.
101 | ],
102 | correct: 3
103 | },
104 | {
105 | question: In Angular, what is a directive?,
106 | answers: [
107 | An Angular feature that takes an element and gives it new functionality.,
108 | A reusable component.,
109 | A combination of HTML and JavaScript that will execute together.,
110 | All of the above.
111 | ],
112 | correct: 3
113 | },
114 | {
115 | question: What does strict mode do?,
116 | answers: [
117 | Makes code more optimizable.,
118 | Adds restrictions to prevent errors.,
119 | Prevents the use of global variables and the use of dangerous code like with
and eval
.,
120 | All of the above.
121 | ],
122 | correct: 3
123 | },
124 | {
125 | question: What is event bubbling?,
126 | answers: [
127 | When the browser engine searches down the DOM tree for event handlers.,
128 | When the browser engine searches up the DOM tree for event handlers.,
129 | When the browser engine searches sideways on sibling elements for event handlers.,
130 | None of the above.
131 | ],
132 | correct: 1
133 | },
134 | {
135 | question: What is event delegation?,
136 | answers: [
137 | Attaching event handlers to child elements rather than parent elements.,
138 | Creating custom event handlers.,
139 | Attaching event handlers to a parent element rather than multiple child elements.,
140 | None of the above.
141 | ],
142 | correct: 2
143 | },
144 | {
145 | question: What is dependency injection?,
146 | answers: [
147 | There's no such thing.,
148 | A type of data structure.,
149 | A coding pattern in which a class receives the instances of objects it needs from an external source rather than creating them itself.,
150 | A new drug the kids are doing nowadays.
151 | ],
152 | correct: 2
153 | },
154 | {
155 | question: What are the six primitive data types in JavaScript?,
156 | answers: [
157 | Function, String, Undefined, Digit, Nil, and Double.,
158 | Boolean, Null, Undefined, Number, String, and Symbol in ES6.,
159 | Number, Class, Object, Hash, String, and Function.,
160 | None of the above.
161 | ],
162 | correct: 1
163 | },
164 | {
165 | question: Which of the following is FALSE about the this
keyword?,
166 | answers: [
167 | Its value is established at the invocation of a function.,
168 | When a function is invoked with the new
keyword, this
is bound to the new object.,
169 | Its value is set at the declaration of a function.,
170 | None of the above.
171 | ],
172 | correct: 2
173 | },
174 | {
175 | question: In Angular 2, which of the following are considered Structural Directives (directives that change DOM layout)?,
176 | answers: [
177 | NgFor
and NgIf
,
178 | NgStyle
and NgClass
,
179 | NgModel
and NgForm
,
180 | None of the above.
181 | ],
182 | correct: 0
183 | },
184 | {
185 | question: Which is TRUE about the events load
and DOMContentLoaded
?,
186 | answers: [
187 | The DOMContentLoaded
event comes after the load
event.,
188 | DOMContentLoaded
is fired when the document has been loaded and parsed; load
fires when all files have finished loading, including images.,
189 | The load
event is fired when only the DOM is loaded and parsed. DOMContentLoaded
is fired when the document is fully loaded, including images.,
190 | They're the same thing.
191 | ],
192 | correct: 1
193 | },
194 | {
195 | question: Which of the following is NOT an example of a data structure in JavaScript?,
196 | answers: [
197 | Object,
198 | Array,
199 | Set in ES2015,
200 | Trie
201 | ],
202 | correct: 3
203 | },
204 | {
205 | question: Which of the following values is truthy?,
206 | answers: [
207 | 0
,
208 | ""
(empty string),
209 | 1
,
210 | undefined
211 | ],
212 | correct: 2
213 | },
214 | {
215 | question: What is an IIFE?,
216 | answers: [
217 | Immediately Iterable Function Evaluation,
218 | Immediately Invoked Function Expression,
219 | Initially Integrated Functional Element,
220 | Internally Indexed File Extension
221 | ],
222 | correct: 1
223 | },
224 | {
225 | question: In React, what method is used to change state?,
226 | answers: [
227 | changeState()
,
228 | onChange()
,
229 | setState()
,
230 | stateSet()
231 | ],
232 | correct: 2
233 | },
234 | {
235 | question: Which of the following is an aspect of a pure function?,
236 | answers: [
237 | Doesn't have unintended side effects.,
238 | Doesn't rely on, or affect, external state.,
239 | Given the same input, it'll always return the same output.,
240 | All of the above.
241 | ],
242 | correct: 3
243 | },
244 | {
245 | question: Where is JavaScript used besides the browser?,
246 | answers: [
247 | Servers, databases, operating systems,
248 | Desktop apps, mobile web apps, mobile hybrid apps, mobile native apps,
249 | Robots, drones, Internet of Things devices,
250 | All of the above.
251 | ],
252 | correct: 3
253 | },
254 | {
255 | question: What are higher order components in React?,
256 | answers: [
257 | They're basically wrappers for other components.,
258 | They take in another component as an argument.,
259 | They're used to extend or modify the behavior of a wrapped component.,
260 | All of the above.
261 | ],
262 | correct: 3
263 | },
264 | {
265 | question: What does the new
keyword do?,
266 | answers: [
267 | Creates a new empty object.,
268 | Sets the prototype of the new object to the constructor's prototype and calls the constructor.,
269 | Sets the this
variable to the new object and returns the new object.,
270 | All of the above.
271 | ],
272 | correct: 3
273 | },
274 | {
275 | question: How is let
different from var
?,
276 | answers: [
277 | let
is block scoped.,
278 | let
isn't hoisted.,
279 | let
can't be redeclared.,
280 | All of the above.
281 | ],
282 | correct: 3
283 | },
284 | {
285 | question: Which of the following is TRUE about the this
keyword?,
286 | answers: [
287 | If a method is called, this
refers to the object that the method is a property of. If the new
keyword is used, this
is the new object instance.,
288 | If call
, apply
or bind
are used, this
is the object that's passed in as the argument.,
289 | If none of the above conditions are met, this
refers to the global object (window
in the browser in non-strict mode; global
in Node).,
290 | All of the above.
291 | ],
292 | correct: 3
293 | },
294 | {
295 | question: Which of the following is something to look out for when using arrow functions?,
296 | answers: [
297 | An arrow function receives the this
value of its surrounding lexical scope at the time it was created; it behaves as if it had been created using fn.bind(this)
.,
298 | If used in an event handler attached to a DOM element, the this
variable will refer to the parent (usually the window) object rather than the element you're targeting.,
299 | An arrow function can't be used as a constructor.,
300 | All of the above.
301 | ],
302 | correct: 3
303 | },
304 | {
305 | question: Which of the following methods can be used to organize/encapsulate code?,
306 | answers: [
307 | The module pattern in ES5 or Module Import Export in ES6.,
308 | An Immediately Invoked Function Expression.,
309 | OO or Objects Linked to Other Objects,
310 | All of the above.
311 | ],
312 | correct: 3
313 | },
314 | {
315 | question: What's an example of a practical use case for recursion?,
316 | answers: [
317 | Traversing a tree (e.g., Walking the DOM).,
318 | Flattening a deeply nested array.,
319 | Deep freezing a deeply nested object.,
320 | All of the above.
321 | ],
322 | correct: 3
323 | },
324 | {
325 | question: What's the difference between =
, ==
, and ===
?,
326 | answers: [
327 | =
is the basic assignment operator. It assigns the value of its right operand to its left operand.,
328 | ==
compares two values for equality AFTER converting both values to a common type.,
329 | ===
is used for strict equality. It checks for equality of both value AND type.,
330 | All of the above.
331 | ],
332 | correct: 3
333 | },
334 | {
335 | question: Which of the following is true about passing by value vs reference?,
336 | answers: [
337 | Objects, arrays, and functions are passed by reference.,
338 | string, number, boolean, symbol, null and undefined are passed by value.,
339 | Primitive types are passed by value and non-primitive types are passed by reference.,
340 | All of the above.
341 | ],
342 | correct: 3
343 | },
344 | {
345 | question: What is a static
method?,
346 | answers: [
347 | A function that exists on an instance, not a class.,
348 | A method that only takes one argument.,
349 | A function that exists on a class, not an instance.,
350 | None of the above.
351 | ],
352 | correct: 2
353 | },
354 | {
355 | question: Which of the following is TRUE about the difference between undefined
and null
.,
356 | answers: [
357 | A variable is undefined
when it's been declared but hasn't been assigned a value.,
358 | null
is purposely assigned as a representation of "no value.",
359 | undefined
is returned when trying to access a non-existant property of an object.,
360 | All of the above.
361 | ],
362 | correct: 3
363 | },
364 | {
365 | question: In React, which of the following is TRUE about the difference between an element and a component?,
366 | answers: [
367 | A React element is an object representation of a DOM node.,
368 | A component is a class
or a function
.,
369 | A component accepts props and returns a React element.,
370 | All of the above.
371 | ],
372 | correct: 3
373 | },
374 | {
375 | question: In React, which is TRUE about the difference between controlled components and uncontrolled components?,
376 | answers: [
377 | With controlled components, form data is handled by React.,
378 | A controlled input accepts its current value as a prop, and a callback to change that value.,
379 | With uncontrolled components, form data is handled by the DOM, and input values can be accessed using refs.,
380 | All of the above.
381 | ],
382 | correct: 3
383 | },
384 | {
385 | question: In React, what's the execution order for methods and lifecycle hooks on initial render?,
386 | answers: [
387 | componentDidMount()
→ render()
→ getDerivedStateFromProps()
→ constructor()
,
388 | render()
→ componentDidMount()
→ constructor()
→ getDerivedStateFromProps()
,
389 | constructor()
→ getDerivedStateFromProps()
→ render()
→ componentDidMount()
,
390 | None of the above.
391 | ],
392 | correct: 2
393 | },
394 | {
395 | question: In React, which is TRUE about the difference between a class component, a PureComponent, and a functional component?,
396 | answers: [
397 | Standard class components have state, lifecycle hooks, and refs.,
398 | A PureComponent is just like a class component, but handles shouldComponentUpdate for you, with a shallow check for changes in props or state. This allows for a performance boost by preventing unnecessary rerenders.,
399 | Functional components are presentational; they don't have access to state or lifecycle hooks, and can't use refs.,
400 | All of the above.
401 | ],
402 | correct: 3
403 | }
404 | ];
405 |
406 | export default QUESTION_DATA;
407 |
--------------------------------------------------------------------------------
/src/helpers/shuffleQuestions.js:
--------------------------------------------------------------------------------
1 | const shuffleQuestions = (arr) => {
2 | return arr.sort((a,b) => Math.random() < .5 ? 1 : -1);
3 | };
4 |
5 | export default shuffleQuestions;
6 |
--------------------------------------------------------------------------------
/src/helpers/tally.js:
--------------------------------------------------------------------------------
1 | const tally = arr => {
2 | return arr.map(item => {
3 | return item.tries;
4 | }).reduce((acc, item) => {
5 | acc[item] = (acc[item] || 0) + 1;
6 | return acc;
7 | }, {});
8 | };
9 |
10 | export default tally;
11 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |