Categories
JavaScript Nodejs

Add Logging to a Koa App with koa-logger

Koa doesn’t come with any logger built-in. Therefore, to see what’s happening with our app, we’ve to log them with a 3rd party logger.

One logger that’s compatible with the Koa framework is the koa-logger package.

Getting Started

To install it, we just run:

npm install koa-logger

and then we can use it by writing:

const logger = require('koa-logger')
const Koa = require('koa')

const app = new Koa()
app.use(logger())

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

All we did is to call use with the return value of the logger middleware passed in, then we get logging automatically.

Now when we start our app, we some output logged.

If we run the code above, we get the following output:

Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
Hint: hit control+c anytime to enter REPL.
Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,
  keepAliveTimeout: 5000,
  maxHeadersCount: null,
  headersTimeout: 40000,
  _connectionKey: '6::::3000',
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(kCapture)]: false,
  [Symbol(asyncId)]: 6
}
  <-- GET / [
Hint: hit control+c anytime to enter REPL.
Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,
  keepAliveTimeout: 5000,
  maxHeadersCount: null,
  headersTimeout: 40000,
  _connectionKey: '6::::3000',
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(kCapture)]: false,
  [Symbol(asyncId)]: 6
}
  <-- GET /
  --> GET / 200 8ms 11b

Custom Logging

The logger middleware function can take an optional callback as an argument.

The callback has the str parameter with the logging output as a string.

args has extra information about the request that’s made, including response time and the size of the response.

We can customize the logging by writing:

const logger = require('koa-logger')
const Koa = require('koa')

const app = new Koa()
app.use(logger((str, args) => {
  console.log(str, args);
}))

app.use(async ctx => {
  ctx.body = 'Hello World';
});

app.listen(3000);

We have the callback:

(str, args) => {
  console.log(str, args);
}

Instead of nothing that we have in the previous example.

The result of this change is the following output:

Server {
  insecureHTTPParser: undefined,
  _events: [Object: null prototype] {
    request: [Function: handleRequest],
    connection: [Function: connectionListener]
  },
  _eventsCount: 2,
  _maxListeners: undefined,
  _connections: 0,
  _handle: TCP {
    reading: false,
    onconnection: [Function: onconnection],
    [Symbol(owner)]: [Circular]
  },
  _usingWorkers: false,
  _workers: [],
  _unref: false,
  allowHalfOpen: true,
  pauseOnConnect: false,
  httpAllowHalfOpen: false,
  timeout: 120000,
  keepAliveTimeout: 5000,
  maxHeadersCount: null,
  headersTimeout: 40000,
  _connectionKey: '6::::3000',
  [Symbol(IncomingMessage)]: [Function: IncomingMessage],
  [Symbol(ServerResponse)]: [Function: ServerResponse],
  [Symbol(kCapture)]: false,
  [Symbol(asyncId)]: 6
}
  <-- GET / [
  '  \u001b[90m<--\u001b[39m \u001b[1m%s\u001b[22m \u001b[90m%s\u001b[39m',
  'GET',
  '/'
]
  --> GET / 200 13ms 11b [
  '  \u001b[90m-->\u001b[39m \u001b[1m%s\u001b[22m \u001b[90m%s\u001b[39m \u001b[32m%s\u001b[39m \u001b[90m%s\u001b[39m \u001b[90m%s\u001b[39m',
  'GET',
  '/',
  200,
  '13ms',
  '11b'
]

We get extra information from the args object.

Alternatively, we can pass in an object with the transporter property to logger:

app.use(logger({
  transporter: (str, args) => {
    // ...
  }
}))

We can add logging to a Koa app with the koa-logger package, which is very simple to use.

With this, we don’t have to create our own logging solution.

Categories
JavaScript React

Set the Default Checked Value of a React Radio Button

To create a radio button group with React and set the default checked value of it, we have to set the value to the state that we want.

Then we’ve to set the checked prop to be the expression to compare the value of the radio button with the currently selected value.

This way, React will check the right one.

We also need an onChange handler to update the state to the right value.

To do all that, we write:

import React, { useState } from "react";

const fruits = ["orange", "apple", "grape"];

export default function App() {
  const [fruit, setFruit] = useState("apple");
  return (
    <div className="App">
      {fruits.map(f => (
        <>
          <input
            type="radio"
            name="fruit"
            value={f}
            checked={fruit === f}
            onChange={e => setFruit(e.currentTarget.value)}
          />{" "}
          {f}
        </>
      ))}
      <p>{fruit}</p>
    </div>
  );
}

We have the fruits array, which we use to map the values to radio buttons.

Radio buttons are input elements with type 'radio'.

The name attribute also have to be set to the same name so that we know that they’re in the same group.

The value attribute is set to the fruit state, so that we can update the checked value by comparison fruit with the value of the value attribute of the radio button.

We have:

onChange={e => setFruit(e.currentTarget.value)}

which gets the e.currentTarget.value property, which has the currently checked radio buttons’ value and set it as the value of the fruit state.

This will update the radio button when we click on it.

Then we display the value of the radio button that’s checked below so that we can see what we actually selected.

To set the default value, we just set the initial value of the fruit state since we used that as the value of the value prop.

The button that’s clicked should have the same value that’s displayed.

To set the default value of a React radio button element, we just have to set the value prop to the state value that we want.

Categories
JavaScript React

Set a Default Value for a React Select Element

We can set the default value of a React select element by using the useState hook.

The default value can be set as the default value of the hook. Then we can set it as the value of the value prop of the select element.

For instance, we can write:

import React, { useState } from "react";

const fruits = ["orange", "apple", "grape"];

export default function App() {
  const [fruit, setFruit] = useState("apple");
  return (
    <div className="App">
      <select
        value={fruit}
        onChange={e => setFruit(fruits[e.target.selectedIndex])}
      >
        {fruits.map(f => (
          <option value={f}>{f}</option>
        ))}
      </select>
      <p>{fruit}</p>
    </div>
  );
}

We set the value prop to fruit so that we set the initial value of it.

We map the fruits entries to the option elements.

Then we add an onChange handler to call setFruit as we change selection.

We get the selected value from the fruits array by writing:

fruits[e.target.selectedIndex]

so that we get the string given the index of the selected option.

Then we display the selected value so that we can see what we selected below the select element.

Since we set the initial value of the fruit state to 'apple', that’s what we display when we load the select element, which means that it’s the default value.

Now we can have default values for our React select elements.

Categories
JavaScript React

React – How to Get Form Values on Submit

To get form values on submit, we can pass in an event handler function into the onSubmit prop to get the inputted form values.

To do that, we write:

import React from "react";

export default function App() {
  const [name, setName] = React.useState("");
  const handleSubmit = e => {
    e.preventDefault();
    console.log(name);
  };
  return (
    <div className="App">
      <form onSubmit={handleSubmit}>
        <input
          typ="text"
          value={name}
          onChange={e => setName(e.target.value)}
        />
        <br />
        <input type="submit" />
      </form>
    </div>
  );
}

We use the useState hook so that we can use the phone state as the value of the value prop.

The onChange prop has a function that calls setName returned by the useState prop to set the value of name with it.

Then we can enter something and see what we entered.

Then we defined the handleSubmit function, which takes an event object e as a parameter.

We’ve to call e.preventDefault to prevent the default server-side submit behavior.

Then we log the value of name to show the value of it in the console.

Now when we enter something and press the Submit button, we’ll see the value of what we entered logged in the console.

With React, getting form values on submit isn’t hard to do. We just have to pass an event handler function to the onSubmit that takes an event object parameter.

Then inside it, we call preventDefault and then we can get the inputted form field data from the state as long as we set the inputted value to a state variable with the onChange handler.

Categories
JavaScript React

How to Add a React Input with a Required Attribute

In a React app, if we want to add input with a required attribute, then we can’t just use the required attribute since we’re supposed to handle all the form input changes ourselves.

However, we can make this task easier by using a library to make our lives easier.

The React Hook Form package lets us add an input field with a required attribute and enforce it by providing functions that we can pass into the props of an input element to enforce an input value to be entered.

To start, we run:

npm install react-hook-form

Then we can write the following to add an input box that requires an input value before form submission.

import React from "react";
import { useForm } from "react-hook-form";

export default function App() {
  const { register, handleSubmit, watch, errors } = useForm();
  const onSubmit = data => console.log(data);
  return (
    <div className="App">
      <form onSubmit={handleSubmit(onSubmit)}>
        <input name="requiredField" ref={register({ required: true })} />
        <br />
        {errors.requiredField && <span>This field is required</span>}
        <br />
        <input type="submit" />
      </form>
    </div>
  );
}

We have an input element that has the ref prop set to the object returned by the register function that’s returned by the useForm hook.

{ required: true } is passed into the register function to make this input a required input.

We also set the name attribute with a name so that we can display form validation error messages below it, which is stored in the returned errors object.

The errors object is returned by useForm and has the form validation errors with the name attribute values of each input element as the keys and true if there are errors in the input field value and false otherwise.

handleSubmit is the form submit event handler, and it doesn’t run until all form input values in the form are valid.

We just log the entered values, which are stored in the data parameter as an object with the keys being the name attribute values of each input and the values being the corresponding input values for each input.

Form validation errors are only detected after we type in something for the first time.

With the React Hook Form package, we can add a React input that acts like it has the required attribute set to true.

We can set an input to be a required input element by passing in some props.