#100DaysOfMERN - Day 12

#100DaysOfMERN - Day 12

·

9 min read

✏ Change of Plan

I had originally planned to write more about JavaScript Promises and then proceed to the Fetch API, but I'm getting a bit unsatisfied with only reading about those methods and working on simple code snippets. Reading about concepts makes sense if you start at 0, but at some point, you'll have to use those concepts in a real project, otherwise you'll just forget them.

There are a few more methods related to Promises that I haven't covered, but I'll write about those when I encounter them in an actual project.

The Fetch API is very simple to use and doesn't need much explanation. fetch() returns a Promise, and does basically the same as what I manually coded with a XMLHttpRequest.

For these reasons, I've decided to tackle a small project: A Quiz App with React, using the Open Trivia DB. It's obviously not a MERN application, since I'll write no back end code, but this should deepen my understanding of how to fetch data and process it in a React App.


✏ React Quiz App

I won't use create-react-app, but install everything manually. I already did that on Day 3, but this time I'll include some more packages for convenience.

I'll basically follow the steps from this article: How to Create a React Development Build, with some modifications.

Step 1

Creating the project folder and initialising it:

mkdir react-quiz
cd react-quiz
npm init

Step 2

Installing React:

npm i react react-dom

Step 3

Installing everything from Webpack and saving it as dev dependency:

npm i --save-dev webpack webpack-cli html-webpack-plugin webpack-dev-server

Also, some loaders:

npm i --save-dev html-loader css-loader style-loader

Step 4

Next, Babel:

npm i --save-dev @babel/core @babel/preset-env @babel/preset-react babel-loader

Step 5

Installing ESLint as a helping hand:

npm i --save-dev eslint eslint-webpack-plugin eslint-plugin-react babel-eslint

Step 6

Configuration files for Webpack, Babel and ESLint:

webpack.config.js

const HtmlWebPackPlugin = require("html-webpack-plugin");
const ESLintPlugin = require('eslint-webpack-plugin');

module.exports = {
    "mode": "development",
    "entry": "./src/index.js",
    "output": {
        "path": __dirname + '/public',
        "filename": "bundle.js"
    },
    "devtool": "source-map",
    "module": {
        "rules": [
            {
                "test": /\.(js|jsx)$/,
                "exclude": /node_modules/,
                "use": {
                    "loader": "babel-loader"
                }
            },
            {
                "test": /\.css$/,
                "use": [
                    "style-loader",
                    "css-loader"
                ]
            },
            {
                "test": /\.html$/,
                "use": [
                    {
                        "loader": "html-loader"
                    }
                ]
            }
        ]
    },
    "plugins": [
        new HtmlWebPackPlugin({
            template: "./src/index.html",
            filename: "./index.html"
        }),
        new ESLintPlugin({})
    ]
}

.babelrc

{
    "presets": [ "@babel/preset-env", "@babel/preset-react" ]
}

.eslintrc.js

module.exports = {
    "env": {
        "browser": true
    },
    "plugins": [ "react" ],
    "extends": [
      "eslint:recommended",
      "plugin:react/recommended"
    ],
    "parser": "babel-eslint"
};

Step 7

Creating a src folder with these files for the basic boilerplate:

  • index.js
  • index.html
  • App.js
  • App.scss

Step 8

Check if everything works as it should:

npx webpack

Awesome, index.html and bundle.js file successfully created.

Step 9

Adding some scripts in the package.json:

package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "start": "webpack serve --mode development --open --hot"
  }

Step 10

Starting the server 🚀

npm start

I get some warnings in the console that seem to be related to ESLint and that I haven't entirely figured out yet, but the environment is working and I can't wait to start building, so I'll just ignore those 🤟


✏ Components

Checking out the Quiz API documentation, you can select a few options (questions genre, multiple choice yes/no, ...), so I'll make an Options component. Also two stateless components Header and Footer, and the actual Quiz.


✏ Fighting with ESLint

I'm beginning to understand the convenience of create-react-app. With my current setup, ESLint throws tons of errors that (how I'm used to it) should just be warnings. I do understand the no-unused-vars rule and I do like that ESLint informs me, but while I'm developing, I really don't need to have an error thrown at me each time.

Adjusting the config file to add a set of rules:

.eslintrc.js

module.exports = {
    "env": {
        "browser": true
    },
    "plugins": [ "react" ],
    "extends": [
      "eslint:recommended",
      "plugin:react/recommended"
    ],
    "rules": {
        "react/prop-types": "off",
        "react/jsx-key": "warn",
        "no-unused-vars": "warn"
    },
    "parser": "babel-eslint"
};

✏ Current Code

The App component

The structure is as follows:

App
| Header
| Options
| | Select
| Quiz
| Footer

The Options component

In this component, I want to show different option dropdowns, and update state in the App component accordingly.

I guess I could've gone for the standard <select> and <option> HTML tags, but I find that styling those to make them look half-decent is a pain. I understand that a uniform look for form elements makes sense regarding accessibility, but I'm not building anything that'll ever go in production. So I've made my own <Select /> component that only uses <div> tags.


The current code works, but there's probably no point in posting it now, before some serious refactoring.


✏ Recap

I've learned

  • how much I prefer building things over reading documentation when it's not immediately necessary
  • how to set up a more sophisticated environment for a React App without create-react-app
  • how to configure ESLint

✏ Next:

  • writing the code for the actual API call using fetch()
  • displaying the questions

✏ Thanks for reading!

I do my best to thoroughly research the things I learn, but if you find any errors or have additions, please leave a comment below, or @ me on Twitter. If you liked this post, I invite you to subsribe to my newsletter. Until next time 👋


✏ Previous Posts

  • Day 1: Introduction, Node.js, Node.js in the terminal
  • Day 2: npm, node_modules, package.json and package-lock.json, local vs global installation of packages
  • Day 3: Create a React app without create-react-app, Webpack, Babel
  • Day 4: npx and cowsay
  • Day 5: npm vs. npx, npm audit, semantic versioning and update rules
  • Day 6: Call stack, event loop, JavaScript engine, JavaScript runtime
  • Day 7: Call stack and event loop in Node.js, setImmediate()
  • Day 8: setImmediate(), process.nextTick(), event loop phases in Node.js
  • Day 9: Network requests with XMLHttpRequest and callbacks
  • Day 10: Promises
  • Day 11: Network requests with XMLHttpRequest and Promises