Principal Software Engineer at Allscipts in Malvern, Pennsylvania, Microsoft Windows Dev MVP, Husband, Dad and Geek.
51828 stories
·
22 followers

✨ Creating A React App

1 Share

Photo by Rolands Zilvinskis on Unsplash

Last week, I gave my own brief history of web sites and how their frontend implementation has drifted from entirely server-based, to entirely client-based, and is now settling (perhaps) with hybrid that we call server-side rendering (SSR). The goal of this journey is to poke around the gnarly bones of SSR and learn what we learn. We may make mistakes, break idioms, and portray ourselves as fools, but we will definitely learn. For that reason, we are not going to bother with things like Next.js, which have already fleshed over and hidden away the gnarly bones for us1.

Now, before we dip even further in the specific world of SSR, we are going to need an app. To be specific, we are going to need a React app.

Hello, React World!

Before creating a React app, we need a package manager; either npm or yarn will suffice. Though we could put together our own app from scratch, there is no need to as the handy create-react-app package exists. There are numerous ways to use this, but the easiest is to use yarn create or npx, which will do the work of obtaining the package and executing it all in one go.

For yarn, drop create from the front of create-react-app:

yarn create react-app <app-name-here>

For npx:

npx create-react-app <app-name-here>

I want to also put this in a git repository so I can track my changes. I would normally make a directory, run git init and then get started. In this case, we do not need to as create-react-app takes care of that for us.

So, let's begin. Open a terminal and invoke create-react-app.

yarn create react-app hello-react-world

After executing this, you will have a working React app that uses react-scripts to manage the basics. This is perfect for our initial journey. If we navigate to that directory and run the project, we can see our app in action.

cd hello-react-world
yarn start
Screenshot of the website created by the create-react-app tool. It shows the React logo in blue, over a dark grey background, with the text "Edit src/App.js and save to reload." and a link labelled, "Learn React"

Fantastic. We have an app. Before we do any more, let's get some remote source control underway. I am paranoid of my machine dying and losing all my work, so having an off machine place to store things is really useful. First, add a new repository on your source control site of choice (I prefer GitHub). Second, connect the local repository to the remote one:

git remote add origin <repo-url>
git fetch
git branch --set-upstream-to origin/master master

Since we want our local code to be the first commit and we're pushing to a brand new repository, we can force push what we have.

git push -f

Routing

Okay, we have an app and it is in source control. This is usually a good spot to spend some time setting up code quality tools like eslint and prettier. I am going to be naughty and skip right over that right now and save it for a different post, perhaps. Instead, let us add some routing to our fledgling application.

There are a few options for implementing routing in a React application (some frameworks, like Next.js, even provide it out of the box). We are going to use React Router. There are two variants of React Router; one for React on websites, and one for React Native on mobile. We want the website variant, which is provided by the react-router-dom package.

yarn add react-router-dom

Now we will edit our app to have a couple of routes. The main app is defined in the src/App.js file. It should look something like this. I have highlighted the lines we're going to replace; we are also going to add some too.

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

There are two things we want to add.

  1. The routes to render our pages.
  2. The links to navigate to our routes.

First we import four things from react-router-dom:

  1. BrowserRouter
    This is the root of our React Router-based navigation. Basically, the router is responsible for the routing (I'm sure you guessed that).
  2. Link
    This replaces the anchor tag (<a>) for our navigation.
  3. Route
    This is used to render a matched route.
  4. Switch
    This allows us to specify a table of possible routes that can be used to work out what should handle the URL currently being viewed.

With these things, we can then add some routes. I am adding Home, About, and Contact. Here is my app code after the edit. I have highlighted the new lines.

import React from 'react';
import {BrowserRouter, Link, Route, Switch} from "react-router-dom";
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <BrowserRouter>
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <div className="App-links">
            <Link className="App-link" to="/">Home</Link>
            <Link className="App-link" to="/about">About</Link>
            <Link className="App-link" to="/contact">Contact</Link>
          </div>
        </header>
        <section className="App-content">
          <Switch>
            <Route path="/about">
              This is the about page!
            </Route>
            <Route path="/contact">
              This is the contact page!
            </Route>
            <Route path="/">
              This is the home page!
            </Route>
          </Switch>
        </section>
      </div>
    </BrowserRouter>
  );
}

export default App;
Screenshot of the updated app using React router. The top shows the React logo with three links below it for "Home", "About" and "Contact" all on a dark grey background. Below that is a white region with the text "This is the home page!"

I also edited the CSS a little, but only to make things easier to see. The important bits are the router, wrapping our app, the Link components to perform navigation, and the Route components that render each route. With this, we now have a single page React app that has three pages for home, about, and contact.

This is going to be the application we will eventually render on the server. The important take away at this point is that we are not going to change the functionality of this app in order to achieve our aim. There are some changes we must make to support SSR, but we will not have two versions of the code. The code that runs in the browser will run on the server.

Next time, we are going to setup a server that will perform our SSR and consider what changes we need to make to our application infrastructure in order to support it. We might even get our first server-side rendered page. Until then, thanks for joining me on this continued exploration of server-side rendering using React.


  1. of course, if starting a new project knowing you need SSR, you should explore solutions like Next.js ↩

Read the whole story
alvinashcraft
1 hour ago
reply
West Grove, PA
Share this story
Delete

Using Local Functions to Replace Comments

1 Share

One idea I’ve been thinking about recently is the replacement of comments with local function calls.

Now this idea doesn’t mean that it’s ok to have massive functions that have no functional cohesion but instead in some circumstances it may improve readability.

In C#, local functions were introduced in C# 7.0. They essentially allow you to write a function inside of a method, property get/set, etc.

As an example take the following code:

public static void ProcessSensorData(string data)
{
    // HACK: occasionally a sensor hardware glitch adds extraneous $ signs
    data = data.Replace("$", "");

    string upperCaseName = data.ToUpperInvariant();
    Save(upperCaseName);
}

private static void Save(string data)
{
    // Save somewhere etc.
    Console.WriteLine(data);
}

In the preceding code there is a hack to fix broken sensors that keep adding extra $ signs.

This could be written using a local function as follows:

public static void ProcessSensorData(string data)
{
    FixExtraneousSensorData();
    string upperCaseName = data.ToUpperInvariant();
    Save(upperCaseName);

    void FixExtraneousSensorData()
    {
        data = data.Replace("$", "");
    }
}

Notice in this version, there is a local function FixExtraneousSensorData that strips out the $ signs. This function is named to try and convey the comment that we had before: “occasionally a sensor hardware glitch adds extraneous $ signs”. Also notice the local function has direct access to the variables of the method in which they’re declared, in this case data.

There are other options here of course such as creating a normal non-local class-level function and passing data to it, or perhaps creating and injecting a data sanitation class as a dependency.

Replacing Arrange, Act, Assert Comments in Unit Tests

As another example consider the following test code:

[Fact]
public void HaveSanitizedFullName()
{
    // Arrange
    var p = new Person
    {
        FirstName = "    Sarah ",
        LastName = "  Smith   "
    };

    // Act
    var fullName = p.CreateFullSanitizedName();

    // Assert
    Assert.Equal("Sarah Smith", fullName);
}

Notice the comments separating the logical test phases.

Again these comments could be replaced with local functions as follows:

[Fact]
public void HaveSanitizedFullName_LocalFunctions()
{
    Person p;
    string fullName;

    Arrange();
    Act();
    AssertResults();
    
    void Arrange()
    {
        p = new Person
        {
            FirstName = "    Sarah ",
            LastName = "  Smith   "
        };
    }

    void Act()
    {
        fullName = p.CreateFullSanitizedName();
    }

    void AssertResults()
    {
        Assert.Equal("Sarah Smith", fullName);
    }
}

This version is a lot longer and although we’ve rid ourselves of the comments the test body is a lot longer, with more lines of code, and I think is probably not as readable. Obviously the test is very simple, if you’ve got a lot of test arrange code for example you could just abstract the arrange phase perhaps.

Another option in the test code to remove the comments is to make use of the most basic unit of design – white space. So for example we could remove comments and still give a clue to the various phases as follows:

[Fact]
public void HaveSanitizedFullName_WhiteSpace()
{
    var p = new Person
    {
        FirstName = "    Sarah ",
        LastName = "  Smith   "
    };


    
    var fullName = p.CreateFullSanitizedName();

    

    Assert.Equal("Sarah Smith", fullName);
}

I think the tactical use of local functions like in the first example to replace the hack comment  may be more useful than replacing the (arguably extraneous) arrange act assert comments in tests.

Let me know in the comments if you think this is a good idea, a terrible idea, or something that you might use now and again.

Read the whole story
alvinashcraft
1 hour ago
reply
West Grove, PA
Share this story
Delete

Azure Event Hub Service Telemetry Example with PowerShell

1 Share
Azure Event Hub | Code Samples - In this article we explore how to simulate sending telemetry data to an Azure Event Hub service with PowerShell and JSON.
Read the whole story
alvinashcraft
1 hour ago
reply
West Grove, PA
Share this story
Delete

.NET App Developer Links - 2020-01-20

1 Share
Read the whole story
alvinashcraft
1 hour ago
reply
West Grove, PA
Share this story
Delete

The Morning Brew #2913

1 Share

Information

Read the whole story
alvinashcraft
1 hour ago
reply
West Grove, PA
Share this story
Delete

Double Shot #2517

1 Share

  • ungoogled chromium - If you like the Chrome browser but don't like the amount of information it shares with Google, here's an alternative.
  • The Good Parts of AWS - An opinionated ebook ($38 to purchase).
  • IgniteOS - "Ignite Os is a simple linux OS focused on productivity and git tools, optimized with all drivers to run on Chromebooks, Netbooks and micro boards." Under active development.
  • Cloudron - "Cloudron is a platform that makes it easy to install, manage and secure web apps on your server. You can install Cloudron on your server (from say AWS, Digital Ocean etc), give it a domain name and start installing apps." Free up to 2 apps, then $30/month.
  • JollysFastVNC - Secure VNC/ARD client (which lets me have both Linux & Mac boxes open as remote desktops at the same time).
  • Rete.js - "Rete is a modular framework for visual programming. Rete allows you to create node-based editor directly in the browser. You can define nodes and workers that allow users to create instructions for processing data in your editor without a single line of code."
  • Nota - Terminal-based calculator that handles things like radicals and Greek letters and trig functions.
  • Live Streaming Server Setup - A how-to guide to setting up RTMP on your own infrastructure.
  • Copy & paste from tmux to system clipboard - A tip for the Linux users out there.
  • darken - Javascript library to make dark mode easy to implement.
  • Secure 2FA SSH and PGP using Krypton - Turn your phone into an all-purpose 2FA device.
  • Creating Tables and Querying data with AWS DynamoDB - An introduction.
Read the whole story
alvinashcraft
1 hour ago
reply
West Grove, PA
Share this story
Delete
Next Page of Stories