Creating a Simple Single Page Web App (SPA)

The Reactium foundational framework can be used to build a stand-alone simple Web App. Need a quick React app with routed components, here's how you do it!

TL;DR - from the command line, run:

mkdir myapp
cd myapp

npx reactium init

[ARCLI] > Initialize what type of project?:  (Use arrow keys)
 Reactium (Web Application) 
  Actinium (Web API) 

# Delete the default component
rm -rf src/app/components/Welcome

# Create Your Home Page!
npx reactium component

[ARCLI] > Select directory:  src/app/components
 src/app/components
  src/app/components/common-ui
  
[ARCLI] > Component Name:  Home

[ARCLI] > Route:  /

[ARCLI] > Reactium Hooks?:  Yes

[ARCLI] > Domain file?:  Yes

[ARCLI] > Stylesheet?:  Yes

[ARCLI] > Select stylesheet type:  
  base 
  atoms 
  molecules 
 organisms 
  overrides 
  default 
  mixins
  
[ARCLI] > Preflight checklist:
{
  "destination": "src/app/components/Home",
  "name": "Home",
  "route": "['/']",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-organisms.scss",
  "className": "home",
  "index": true
}

[ARCLI] > Proceed?:  (y/N) y

npm run local  

That's it. You should be looking at a running simple app, with your Home component running on http://localhost:3000

Creating A Page

Let's break down what's happening with the previous reactium command. After proceeding, your scr/app directory should look something like this:

src/app
├── components
│   ├── Home
│   │   ├── Home.jsx
│   │   ├── reactium-domain-home.js <- defines the unique namespace of our component
│   │   ├── reactium-hooks-home.js <- Reactium plugin hooks go here
│   │   ├── reactium-route-home.js <- Defines the Route where this component renders in the front-end
│   │   └── _reactium-style-organisms-Home.scss <- Styles go here
└── main.js <- The main entry point of the app (usually no modifications needed)

Create a Second Page

npx reactium component

[ARCLI] > Select directory:  src/app/components
❯ src/app/components
  src/app/components/common-ui
  
[ARCLI] > Component Name:  About

[ARCLI] > Route:  /about

[ARCLI] > Reactium Hooks?:  Yes

[ARCLI] > Domain file?:  Yes

[ARCLI] > Stylesheet?:  Yes

[ARCLI] > Select stylesheet type:  
  base 
  atoms 
  molecules 
❯ organisms 
  overrides 
  default 
  mixins
  
[ARCLI] > Preflight checklist:
{
  "destination": "src/app/components/About",
  "name": "About",
  "route": "['/about']",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-organisms.scss",
  "className": "about",
  "index": true
}

[ARCLI] > Proceed?:  (y/N) y

Single Page Application Navigation

You already have a React single-page application started.

Let's create a navigation component and render it on both pages!

npx reactium component

[ARCLI] > Select directory:  common-ui
❯ src/app/components/common-ui

[ARCLI] > Component Name:  Nav

[ARCLI] > Route:
[ARCLI] > Reactium Hooks?:  (Y/n)  Yes
[ARCLI] > Domain file?:  (Y/n)  Yes

[ARCLI] > Stylesheet?:  (Y/n) Yes
  variables 
  base 
  atoms 
❯ molecules 
  organisms 
  overrides 
  default 
(Move up and down to reveal more choices)

[ARCLI] > Preflight checklist:

{
  "destination": "src/app/components/common-ui/Nav",
  "name": "Nav",
  "route": "[]",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-molecules",
  "className": "nav",
  "index": true
}

[ARCLI] > Proceed?:  (Y/n) Yes

Ok, let's modify our Nav component:

common-ui/Nav/Nav.jsx
import React from 'react';
import { NavLink } from 'react-router-dom';

/**
 * -----------------------------------------------------------------------------
 * Component: Nav
 * -----------------------------------------------------------------------------
 */
export const Nav = ({ className }) => {
    return (
        <nav className={className}>
            <NavLink to='/' exact={true} activeClassName='active'>
                Home
            </NavLink>
            <NavLink to='/about' activeClassName='active'>
                About
            </NavLink>
        </nav>
    );
};

Nav.defaultProps = {
    className: 'nav',
};

export default Nav;

Let's also add some sassy styles for Nav:

common-ui/Nav/_reactium-style-molecules-Nav.scss
.nav {
    display: flex;
    flex-direction: column;
    padding: 20px;

    a {
      &, &:visited {
        color: gray;
      }
      &:hover, &.active {
        color: black;
      }
    }
}

Great, now let's include the Nav in both the Home page and the About page:

import {
    useSyncState,
    useHookComponent,
} from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: Home
 * -----------------------------------------------------------------------------
 */
export const Home = ({ className }) => {
    const Nav = useHookComponent('Nav');
    const state = useSyncState({ content: 'Home' });

    return (
        <div className={className}>
            <Nav />
            <h1>{state.get('content')}</h1>
            <p>This is the Home page.</p>
        </div>
    );
};

Home.defaultProps = {
    className: 'home',
};

export default Home;
/

Great, Now we are SPA Routing!

But wait, does that mean I have to have common elements like the Nav on every routed page?

Let's create an AppParent component to be the "window dressing" for our app!

npx reactium component

[ARCLI] > Select directory:  common-ui
❯ src/app/components/common-ui

[ARCLI] > Component Name:  AppParent

[ARCLI] > Route:
[ARCLI] > Reactium Hooks?:  (Y/n)  Yes
[ARCLI] > Domain file?:  (Y/n)  Yes

[ARCLI] > Stylesheet?:  (Y/n) Yes
  variables 
  base 
  atoms 
  molecules 
❯ organisms 
  overrides 
  default 
(Move up and down to reveal more choices)

[ARCLI] > Preflight checklist:

{
  "destination": "src/app/components/common-ui/AppParent",
  "name": "AppParent",
  "route": "[]",
  "hooks": true,
  "domain": true,
  "style": true,
  "styleType": "_reactium-style-organisms",
  "className": "appparent",
  "index": true
}

[ARCLI] > Proceed?:  (Y/n) Yes

Let's move the Nav to the AppParent component, and add some common page structure to the app.

import { useHookComponent } from '@atomic-reactor/reactium-core/sdk';
import React from 'react';

/**
 * -----------------------------------------------------------------------------
 * Component: AppParent
 * -----------------------------------------------------------------------------
 */
export const AppParent = ({ className, children }) => {
    const Nav = useHookComponent('Nav');
    const Footer = useHookComponent('Footer');
    return (
        <main className={className}>
            <aside className='main-nav'>
                <Nav />
            </aside>
            <section className='main-content'>{children}</section>
            <footer className='main-footer'>
                <Footer />
            </footer>
        </main>
    );
};

AppParent.defaultProps = {
    className: 'appparent main',
};

export default AppParent;

Final Simple SPA

Front-end Routed Single Page Application

Last updated