DEV Community

Cover image for Shopify App From Scratch #8 - React Sidestep 2
Red Cap Tom
Red Cap Tom

Posted on • Updated on • Originally published at redcaptom.com

Shopify App From Scratch #8 - React Sidestep 2

Deprecation Notice

Yeah, yeah, I know. I hate it too when people abandon tutorial series mid-way. But, due to (exciting!) circumstances, I'm calling it quits for now.

I'm thinking of just dropping a link to the full repo here - it's a mess, but it's something you guys can chew on instead of my empty promises.

If you'd like me to drop it here - let me know at hey@redcaptom.com.

And, just sayin', I had a BLAST doing this. If you know something - anything - about technology, take the time to write it down as a tutorial series. You will get SO, SO much value out of it, you can't even believe it.

Until we meet again - RCT :)

The Video (Scroll down for the article)

Coming soon!

A Short Primer

Before we dive into it, It's important to note that React is just JavaScript. Facebook wrote React as a JavaScript library that deals with scaffolding up the front-end part of a website. This means that you should probably know some JavaScript before you enter this sidestep. If you don't know any javascript, as in you've never written a line of it, go do a tutorial and come back.

Keep in mind that this is just a sidestep - it's not actually a tutorial. It's something that is done in order to familiarize you with the concepts that I'm talking about, so when you look at a syntax or when I'm running through the application we're going to build, you have some idea of what I'm talking about. It's not meant to teach you React - it's just meant to give you a taste of it, and maybe give you some terms you can later Google and dive into properly.

Before we actually install React and play with it a bit, I do want to mention one thing. React, by itself, has two "worlds" in it. The first one, what people usually talk about when they talk about React, is JSX - which is what React components are returning - which kind of looks like HTML and not really like JavaScript. This can be confusing to people. What you should know is React is kind of half-and-half in that sense - one part is what you return to the page (JSX) and a second part is in charge of what, where and when the former JSX gets thrown up on the page.

This is a bit "in the air", and therefore I'd like to dive in and explain as I go along.

Setting up

Given that React is a JavaScript framework, we will use stuff from the JavaScript ecosystem. Specifically, if you come from a a PHP or ASP or those kind of languages, you're used to spinning up a server and putting your stuff there in order to see them run.

If you're on Windows it's probably XAMPP, if you're on a Mac it's probably MAMP and if you're on Linux you probably roll your own configuration. Anyways, what you probably do is running a server (i.e. Apache), putting files in the exposed folder in that server (i.e. htdocs or www) and then serving those files from there by opening your browser to that location.

The JavaScript frameworks usually have a bundled-in server which is very similar to running XAMPP locally, except for the fact that the framework takes care of everything for you.

This is a theme that will become more and more apparent as you dive deeper and deeper into JavaScript frameworks. They have a tendency to do everything for you - lots of packages, lots of stuff out there to save you time and headaches. Everything you can think of - from testing to linting to deploying to... you name it - they have it. This makes the entire "getting started" phase of a project really really fast.

We're going to dive right in. First things first - let's make sure we got the correct version for the project in front of us. This can be done using nvm - Node Version Manager - which we have installed previously. The command nvm use tells nvm to "switch the context" to the correct version of Node. I used V12.13.1 of Node for this project, so we can do:

nvm use 12.13.1

To get the correct version for this project, and you should see a success message telling you that you are now using the correct version. If you don't have that version installed, just do:

nvm install 12.13.1

Scaffolding the project

To get it. We're now going to use npx - which is kind of like a sister tool to npm - that is used to run executables in packages. The actual stuff going on behind the scenes don't really matter right now - it is just used for installation of a scaffolding tool for React called create-react-app. It feels like a build tool for React but that's not really what it does - a better term for it will be a "Scaffolder", so that's what I'm going to use. Run the following to create a new project called react-sidestep, since that's what we are doing right now:

npx create-react-app react-sidestep

It's gonna take a while. If you watch the video, I go most of what the script installed. I think it's a great overview for what is available out of the box with this scaffolding tool.

Note that this created a new folder in the directory you were in called react-sidestep. Go into it by running:

cd react-sidestep

we can now actually run our newly-scaffolded React app by doing:

npm start

And see the following screen pop up in front of us:

react-main-screen

You might note that there are a bunch of files in that folder - see the video for an exact breakdown of what each of the files is actually all about. I also go quite deeply into the JavaScript ecosystem, npm and various interesting things around developing in modern JavaScript.

In Comes React

But, let's get down to business - how React actually looks like in the wild. Let's take a look at the src folder:

src
--| App.css
--| App.js
--| App.test.js
--| index.css
--| index.js
--| logo.svg
--| serviceWorker.js
--| setupTests.js

The entry point to the app - and the interesting tidbit from our end - is index.js, so this is what I'm going to focus on:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

Let's break it bit by bit - the first thing you see is the imports:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

Those imports are either coming from the node_modules folder (i.e. were installed in by definition in the package.json file and/or by npm install <package>), or local files. You can separate the two by the ./ before local files, whereas npm packages just have the package name as the origin of the import.

So react and react-dom are both both packages that are inside the node_modules folder, whereas everything else is originating in some local folder or file inside our project.

The interesting part comes now:

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

React doesn't actually populate HTML tags into your page. What React does is simulate a DOM - the representation of things on a web page - and maintains it completely independently of the actual DOM you see on the page. That DOM is called a Virtual DOM, and it is the best mapping React can create to simulate the behavior you expect to see on a page.

In order to actually understand what this means, let's skip over to the public/index.html file for a second:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <meta
      name="description"
      content="Web site created using create-react-app"
    />
    <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
    <!--
      manifest.json provides metadata used when your web app is installed on a
      user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
    -->
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
    <!--
      Notice the use of %PUBLIC_URL% in the tags above.
      It will be replaced with the URL of the `public` folder during the build.
      Only files inside the `public` folder can be referenced from the HTML.

      Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
      work correctly both with client-side routing and a non-root public URL.
      Learn how to configure a non-root public URL by running `npm run build`.
    -->
    <title>React App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

Specifically, take a look at this part:

    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->

This basically explains the whole thing - React takes care of maintaining some representation of the optimal DOM somewhere in memory, and then adds / remove HTML elements from the page accordingly. Specifically, you can tell it to start adding/removing elements from a specific place in the page, and the most common location to do that is an HTML <div> element with the id of root. Back to our JavaScript for a second:

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

It might make a bit more sense to you now - we're telling ReactDOM to "render" - i.e. throw on the page - something that looks like three HTML tags (but is actually JSX, and we'll talk about that in a second), and then place them inside the root HTML element. This, in essence, means that React will "push" into the <div> whatever it is we ask it to push, and in our specific case it will push:

  <React.StrictMode>
    <App />
  </React.StrictMode>

Under the root element. Note that this is very different than what you might be used to - it's, conceptually at least, "offloading" the creating of the webpage to React. I think it's a great abstraction over what I was previosuly used to, but that's of course up for debate:)

Funcational Components

So what is this mystical JSX that I keep on talking about?

Well, in essence - it is JavaScript. It is a "syntax extension" - which is a fancy way of saying "let's add more words to our language's dictionary" - that allows us to use actual logic when creating our interfaces.

You can have functions, variables, conditionals and other fun things you're used to from your favorite programming langugaes right in JSX - enabling you to refrain from mixing-and-matching PHP, JavaScript and HTML to create screens.

Most of React revolves around "Components" - which are logical pieces of interface that can be swapped around your page, re-used, re-purposed and basically encapsulate everything your interface's "meat".

In our case, <App> is a component - and in actuality the main component of our app. This very similiar, conceptually, to creating custom HTML tags - each representing a set of interface parts grouped together to perform some logic. You will see <Button> and <TextField> components, <Slider> and <Navbar> components and - like here - more fully-featured, complete components like <App>.

<App> is coming from an import, and is actually defined in the App.js file. Let's take a look to see what this component actually looks like:

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;

It seems to revolve around this App() function, right? That is no coincidence, and that is the first type of component I will talk about - a functional component. This might seem a bit weird at first - is this a component, or a function?

Well, as you'll soon see, every component in React is either a function or a class (more about that in the next article in the series). In and of itself, this should not matter to you. All you should understand is that each thing that you see on a page is a function, and understand how those functions compose together to create the UI.

Notice that the App() function is kind of simple - it just has a return clause, that returns a bunch of JSX (which, in this case, is mostly valid HTML). The only weird looking thing is this part:

<img src={logo} className="App-logo" alt="logo" />

What is this {logo} thing doing there? Well, that's the beauty of JSX for you - it's a javascript variable defined here:

import logo from './logo.svg';

Which gets the SVG logo from the file (streamlined by create-react-app) for you to use inside your component. This means that the React logo you saw on the initial screen, is actually imported right here in the component for display!

The rest of the JSX is just valid HTML. Whenever the App component is will be called, like in index.js as we saw before:

  <React.StrictMode>
    <App />
  </React.StrictMode>

React will make sure to place all the JSX returned by the element into is virtual DOM. In this case, App is a rather simple component - but we'll see in a second the power this approach brings us when the component are a bit more complex.

There is one small difference to note here - the class attribute of HTML tags needs to be swapped for className in JSX. This eventually get massaged into the class attribute you know and love, but it's important to mention the very obvious difference from plain HTML.

If you're following along with the video, I stop here to give an example of how to break apart a single component into multiple ones, talk about React Fragments and mess with the default project a bit to show you what's possible.

Props

Props. are values you can pass to a component, and then render different things based on them. For example, in the video I add a participantName prop to the MainInfo component I created. I can then pass to the component different attribute values in different parts of the app. This enables me, for example, to call that component once for a participant named "Tom" and once for a participant named "Not Tom". Both participants will get their own MainInfo component, with the name swapped out based on the value provided to the attribute.

Hooks

React hooks are... a bit tricky. I give an example in the video to a simple hook, but in retrospective I advise you to read the React Hooks intro and Hooks at a Glance for a better overview. They're short and concise, and give you all you need to understand about the syntax to get going, in my opinion.

Final words

This was a very short overview of functional components and the basics of React. Make sure to read the next article in the series to learn about class components, and - if you'd like a deeper dive - check out Dave Ceddia's Pure React book for a more thorough walk through React. This might look like an affiliate link, btw, but it's just a way for me and Dave to track how many visitors I'm sending his way (no money involved).

Latest comments (0)