Reactium App Foundation Reactium Guides 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:
Copy 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:
Copy 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
Copy 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!
Copy 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:
Copy 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
Copy .nav {
display : flex ;
flex-direction : column ;
padding : 20 px ;
a {
& , & :visited {
color : gray ;
}
& :hover , & .active {
color : black ;
}
}
}
Great, now let's include the Nav in both the Home page and the About page:
Home.jsx About.jsx
Copy 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;
Copy import {
useSyncState ,
useHookComponent ,
} from '@atomic-reactor/reactium-core/sdk' ;
import React from 'react' ;
/**
* -----------------------------------------------------------------------------
* Component: About
* -----------------------------------------------------------------------------
*/
export const About = ({ className }) => {
const Nav = useHookComponent ( 'Nav' );
const state = useSyncState ({ content : 'About' });
return (
< div className = {className}>
< Nav />
< h1 >{ state .get ( 'content' )}</ h1 >
< p >This is the About page.</ p >
</ div >
);
};
About .defaultProps = {
className : 'about' ,
};
export default About;
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!
Copy 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.
AppParent.jsx _reactium-style-organisms-AppParent.scss Home.jsx About.jsx _reactium-style-molecules-Nav.scss
Copy 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;
Note that the Footer
component need not actually already exist. If someone creates one with that name, it will just show up!
By creating an AppParent
component that returns props.children
, it will automatically take the place of the component in reactium-core. Registered components are overridden! A good thing!
Copy .main {
padding : 50 px ;
& -nav , & -content {
border-bottom : 1 px solid black ;
}
& -content {
padding : 20 px 0 ;
}
}
Copy import { useSyncState } from '@atomic-reactor/reactium-core/sdk' ;
import React from 'react' ;
/**
* -----------------------------------------------------------------------------
* Component: Home
* -----------------------------------------------------------------------------
*/
export const Home = ({ className }) => {
const state = useSyncState ({ content : 'Home' });
return (
< div className = {className}>
< h1 >{ state .get ( 'content' )}</ h1 >
< p >This is the Home page.</ p >
</ div >
);
};
Home .defaultProps = {
className : 'home' ,
};
export default Home;
Copy import { useSyncState } from '@atomic-reactor/reactium-core/sdk' ;
import React from 'react' ;
/**
* -----------------------------------------------------------------------------
* Component: About
* -----------------------------------------------------------------------------
*/
export const About = ({ className }) => {
const state = useSyncState ({ content : 'About' });
return (
< div className = {className}>
< h1 >{ state .get ( 'content' )}</ h1 >
< p >This is the About page.</ p >
</ div >
);
};
About .defaultProps = {
className : 'about' ,
};
export default About;
Copy .nav {
display : flex ;
a {
padding : 10 px 20 px ;
& ,
& :visited ,
& :hover ,
& :active {
text-decoration : none ;
}
& ,
& :visited {
color : gray ;
}
& :hover ,
& .active {
color : white ;
background : gray ;
}
}
}
Final Simple SPA