5 Handy ReactJS Hints You Need to Know (part2)

Previously I decided to start a series of small tips in ReactJS that could be handy in implementing a React application. I published the first episode a while ago and now want to share the second one. The episodes are not connected so you can read them without order.

Before we start, here is my React package.json so you know which versions I am using:

"dependencies": {
    "@testing-library/jest-dom": "^5.16.3",
    "@testing-library/react": "^12.0.0",
    "@testing-library/user-event": "^12.0.0",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-router-dom": "^5.2.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4",
    "query-string": "^7.1.1"
  },

Let’s start!

Event listener in React

We all know that in JQuery, we can bind event listeners to classes and elements. For example, we use onClick() event to perform something when a user clicks on certain elements on the page.

Attention: In React, we usually do not handle stuff with event listeners like JQuery. Most of the time we use state variables to perform things when the component state changes (like when a user clicks on a thing, it changes the state).

However, sometimes we need event listeners. For instance, when something needs to be done after a keyboard key is pressed. So how can we do it? with our old friend Javascript.

Let’s say we have this function. We want to call this function when a user presses a key on the keyboard.

processKey(event){
   // do something after a user presses a key
}

To do a bind, we use the JS addEventListener() function. We need to use it when the component is loaded. In a class component, this means the componentDidMount() function.

componentDidMount(){
    document.addEventListener("keydown", this.processKey);                    
}

We also need to remove this event when the component is going down in order to avoid unwanted side effects (the event is bound to the document). So remember to do this also in the componentWillUnmount() function:

componentWillUnmount(){
   document.removeEventListener("keydown", this.processKey);
}

Create HTML element

It happens that sometimes we want to create a new HTML element such as a <div> and add it to our view. In old Javascript and JQuery, this was super common.

Attention: In Reac, however, there are better ways to do it such as using and updating state variables that we use to render the content.

But, sometimes we need to add something anyway. So how do we do it?

We can use the createElement in React. It takes three main arguments:

  • The element name
  • properties (such as class and id)
  • child or list of children

So it would be like:

import React from "react";

let icon = React.createElement("i", {"className": "fa fa-plus", "aria-hidden": "true"}, "");
let text = React.createElement("p", {}, "My Text");
let node = React.createElement("div", { "className": "my-class", "id": "myId"}, [icon, text]);

This will result in:

<div class="my-class" id="myId">
    <i class="fa fa-plus" aria-hidden=true></i>
    <p>My Text </p>
</div>

Copy button with Confirm Symbol

This is quite common in web apps. Sometimes you have a link or text and you want to let users copy the link or text by clicking a button instead of selecting and copying it manually.

It is also common to show visual feedback to the user, such as a check sign, to let the user know the content is successfully copied to the clipboard.

To do this:

  • We bind an onclick event to our copy button
  • We use the navigator object in Javascript to copy the target content to the clipboard
  • We use a state variable in React to know whether the copy is done or not. If yes, then we show the check sign to the user.
import { useState } from 'react';

const [copied, setCopied] = useState(false);

<button type="button" class="btn"
      onClick={() => {                  
           navigator.clipboard.writeText("The Thing We Want to Copy to Clipboard");
           setCopied(true);
      }}
> Copy Me {copied && <i class="fa fa-check" aria-hidden="true"></i>}</button>  

Download a JSON object

Let’s say we have some data as JSON in our application and we want to let users download this data as a JSON file. How can we do it?

The main trick here is that we need to do three steps:

  • Create an actual file from the JSON object
  • Make a hidden download anchor and implicitly click it to trigger the download
  • Remove the download anchor after the download

Let’s look at the script first:

<a 
    className='btn btn-primary'                                
    onClick={async () => {                    
            const jsonFile = JSON.stringify(targetJson);
            const blob = new Blob([jsonFile],{type:'application/json'});
            const href = await URL.createObjectURL(blob);
            const link = document.createElement('a');
            link.href = href;
            link.download = "myCustomFileName.json";
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
         }}
>
  <i class="fa fa-download"></i>Download file as JSON</a>
  • We first stringify the JSON object
  • Then we use the blob (Binary Large Object) datatype in Javascript to create a virtual JSON file
  • Then we create the hidden anchor and set the target URL to the blob file that we created
  • We also give the target file a name. This will be the downloaded file name. (myCustomFileName.json)
  • We click the anchor (download starts)
  • Finally, we remove the anchor

Required Login to render

The last tip for this post is about Login and authentication. It is super common to check for the user login status for rendering a component in React.

There are many ways to do this. But the way I like is to use a wrapper that checks the login status and renders the target component if the user is logged in.

Why?

Business logic always changes. Today something requires a logged-in user and in two months not. It is difficult to change each component if this happens. Besides, sometimes you are using a third-party component and you do not want to change its logic to include your login logic. It is better to wrap them in a component that renders the target components conditionally.

In the below code, the function isLogin() is supposed to check the user authentication status by calling an API. The API is supposed to send an answer like True or False. Based on the response, we either render the target component or render nothing.

Note: You can change the response checking part based on the outcome of your login checker function. This is just a simple scenario for this blog post.

import { useState } from "react";

function RenderIfLogin({component: Component}){
    const [loginStatus, setLoginStatus] = useState(null);    
    isLogin().then((resp) => {
        setLoginStatus(resp);
    });
    
    if (loginStatus) {
        return Component;
    }
    return "";
}

export default RenderIfLogin;

To use this wrapper, we can do something like this:

<RenderIfLogin component={<LoginNeededComponent />} />

The target component to render conditionally is LoginNeededComponent.

Hope you find these points useful.

The End.