Build a Basic CRUD App with Node and React

Build a Basic CRUD App with Node and React

Learn how to build a simple app with Node and React: register and login users, store data in a database, etc.

Learn how to build a simple app with Node and React: register and login users, store data in a database, etc.

There are a lot of JavaScript frameworks out there today. It seems like I hear about a new one every month or so. They all have their advantages and are usually there to solve some sort of problem with an existing framework. My favorite to work with so far has been React. One of the best things about it is how many open source components and libraries there are in the React ecosystem, so you have a lot to choose from. This can be really difficult if you’re indecisive, but if you like the freedom to do things your way then React may be the best option for you.

In this tutorial, I’ll walk you through creating both a frontend web app in React and a backend REST API server in Node. The frontend will have a home page and a posts manager, with the posts manager hidden behind secure user authentication. As an added security measure, the backend will also not let you create or edit posts unless you’re properly authenticated.

The tutorial will use Okta’s OpenID Connect (OIDC) to handle authentication. On the frontend, the Okta React SDKwill be used to request a token and provide it in requests to the server. On the backend, the Okta JWT Verifier will ensure that the user is properly authenticated, and throw an error otherwise.

The backend will be written with Express as a server, with Sequelize for modeling and storing data, and Epilogue for quickly creating a REST API without a lot of boilerplate.

Why React?

React has been one of the most popular JavaScript libraries for the past few years. One of the biggest concepts behind it, and what makes it so fast, is to use a virtual DOM (the Document Object Model, or DOM, is what describes the layout of a web page) and make small updates in batches to the real DOM. React isn’t the first library to do this, and there are quite a few now, but it certainly made the idea popular. The idea is that the DOM is slow, but JavaScript is fast, so you just say what you want the final output to look like and React will make those changes to the DOM behind the scenes. If no changes need to be made, then it doesn’t affect the DOM. If only a small text field changes, it will just patch that one element.

React is also most commonly associated with JSX, even though it’s possible to use React without JSX. JSX lets you mix HTML in with your JavaScript. Rather than using templates to define the HTML and binding those values to a view model, you can just write everything in JavaScript. Values can be plain JavaScript objects, instead of strings that need to be interpreted. You can also write reusable React components that then end up looking like any other HTML element in your code.

Here’s an example of some JSX code, that should be fairly simple to follow:

const Form = () => (
  
    
      Name
      
    
    
      Answer to life, the universe, and everything
      
    
  
);

const App = () => (
  
    # Welcome, Hitchhiker!

    
  
);


…and here’s what the same code would look like if you wrote it in plain JavaScript, without using JSX:

const Form = () => React.createElement(
  "form",
  null,
  React.createElement(
    "label",
    null,
    "Name",
    React.createElement("input", { value: "Arthur Dent" })
  ),
  React.createElement(
    "label",
    null,
    "Answer to life, the universe, and everything",
    React.createElement("input", { type: "number", value: 42 })
  )
);

const App = () => React.createElement(
  "main",
  null,
  React.createElement(
    "h1",
    null,
    "Welcome, Hitchhiker!"
  ),
  React.createElement(Form, null)
);


I find the JSX form much easier to read, but that’s just like, you know, my opinion, man.

Create Your React App

The quickest way to get started with React is to use Create React App, a tool that generates a progressive web app (PWA) with all the scripts and boilerplate tucked away neatly behind something called react-scripts, so you can just focus on writing code. It has all kinds of nice dev features as well, like updating the code whenever you make changes, and scripts to compile it down for production. You can use npm or yarn, but I’ll be using yarn in this tutorial.

To install create-react-app and yarn, simply run:

npm i -g [email protected] [email protected]


NOTE: I’ll be adding version numbers to help future-proof this post. In general though, you’d be fine leaving out the version numbers (e.g. npm i -g create-react-app).

Now bootstrap your application with the following commands:

create-react-app my-react-app
cd my-react-app
yarn start


The default app should now be running on port 3000. Check it out at [http://localhost:3000](http://localhost:3000 "http://localhost:3000").

Create a Basic Homepage in React with Material UI

To keep things looking nice without writing a lot of extra CSS, you can use a UI framework. Material UI is a great framework for React that implements Google’s Material Design principles.

Add the dependency with:

yarn add @material-ui/[email protected]


Material recommends the Roboto font. You can add it to your project by editing public/index.html and adding the following line inside the head tag:




You can separate components into separate files to help keep things organized. First, create a couple new folders in your src directory: components, and pages

mkdir src/components
mkdir src/pages


Now create an AppHeader component. This will serve as the navbar with links to pages, as well as show the title and whether you’re logged in.

src/components/AppHeader.js

import React from 'react';
import {
  AppBar,
  Toolbar,
  Typography,
} from '@material-ui/core';

const AppHeader = () => (
  
    
      
        My React App
      
    
  
);

export default AppHeader;


Also create a homepage:

src/pages/Home.js

import React from 'react';
import {
  Typography,
} from '@material-ui/core';

export default () => (
  Welcome Home!
);


Now go ahead and actually just gut the sample app, replacing src/App.js with the following:

src/App.js

import React, { Fragment } from 'react';
import {
  CssBaseline,
  withStyles,
} from '@material-ui/core';

import AppHeader from './components/AppHeader';
import Home from './pages/Home';

const styles = theme => ({
  main: {
    padding: 3 * theme.spacing.unit,
    [theme.breakpoints.down('xs')]: {
      padding: 2 * theme.spacing.unit,
    },
  },
});

const App = ({ classes }) => (
  
    
    
    
      
    
  
);

export default withStyles(styles)(App);


Material UI uses JSS (one of many flavors in the growingly popular trend of CSS in JavaScript), which is what withStyles provides.

The CssBaseline component will add some nice CSS defaults to the page (e.g. removing margins from the body), so we no longer need src/index.css. You can get rid of a couple other files too, now that we’ve gotten rid of most of the Hello World demo app.

rm src/index.css src/App.css src/logo.svg


In src/index.js, remove the reference to index.css (the line that says import './index.css';). While you’re at it, add the following as the very last line of src/index.js to turn on hot module reloading, which will make it so that changes you make automatically update in the app without needing to refresh the whole page:

if (module.hot) module.hot.accept();


At this point, your app should look like this:

Add Authentication to Your Node + React App with Okta

You would never ship your new app out to the Internet without secure identity management, right? Well, Okta makes that a lot easier and more scalable than what you’re probably used to. Okta is a cloud service that allows developers to create, edit, and securely store user accounts and user account data, and connect them with one or multiple applications. Our API enables you to:

If you don’t already have one, sign up for a forever-free developer account. Log in to your developer console, navigate to Applications, then click Add Application. Select Single-Page App, then click Next.

Since Create React App runs on port 3000 by default, you should add that as a Base URI and Login Redirect URI. Your settings should look like the following:

Click Done to save your app, then copy your Client ID and paste it as a variable into a file called .env.local in the root of your project. This will allow you to access the file in your code without needing to store credentials in source control. You’ll also need to add your organization URL (without the -admin suffix). Environment variables (other than NODE_ENV) need to start with REACT_APP_ in order for Create React App to read them, so the file should end up looking like this:

.env.local

REACT_APP_OKTA_CLIENT_ID={yourClientId}
REACT_APP_OKTA_ORG_URL=https://{yourOktaDomain}


The easiest way to add Authentication with Okta to a React app is to use Okta’s React SDK. You’ll also need to add routes, which can be done using React Router. I’ll also have you start adding icons to the app (for now as an avatar icon to show you’re logged in). Material UI provides Material Icons, but in another package, so you’ll need to add that too. Run the following command to add these new dependencies:

yarn add @okta/[email protected] [email protected] @material-ui/[email protected]


For routes to work properly in React, you need to wrap your whole application in a Router. Similarly, to allow access to authentication anywhere in the app, you need to wrap the app in a Security component provided by Okta. Okta also needs access to the router, so the Security component should be nested inside the router. You should modify your src/index.js file to look like the following:

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { Security } from '@okta/okta-react';

import App from './App';
import registerServiceWorker from './registerServiceWorker';

const oktaConfig = {
  issuer: `${process.env.REACT_APP_OKTA_ORG_URL}/oauth2/default`,
  redirect_uri: `${window.location.origin}/implicit/callback`,
  client_id: process.env.REACT_APP_OKTA_CLIENT_ID,
};

ReactDOM.render(
  

    
      
    
  ,
  document.getElementById('root'),
);
registerServiceWorker();

if (module.hot) module.hot.accept();


Now in src/App.js you can use Routes. These tell the app to only render a certain component if the current URL matches the given path. Replace your Home component with a route that only renders the component when pointing at the root URL (/), and renders Okta’s ImplicitCallback component for the /implicit/callback path.

src/App.js

--- a/src/App.js
+++ b/src/App.js
@@ -1,4 +1,6 @@
 import React, { Fragment } from 'react';
+import { Route } from 'react-router-dom';
+import { ImplicitCallback } from '@okta/okta-react';
 import {
   CssBaseline,
   withStyles,
@@ -21,7 +23,8 @@ const App = ({ classes }) => (
     
     
     
-      
+      
+      
     
   
 );


Next, you need a login button. This file is a bit bigger because it contains some logic to check if the user is authenticated. I’ll show you the whole component first, then walk through what each section is doing:

src/components/LoginButton.js

import React, { Component } from 'react';
import {
  Button,
  IconButton,
  Menu,
  MenuItem,
  ListItemText,
} from '@material-ui/core';
import { AccountCircle } from '@material-ui/icons';
import { withAuth } from '@okta/okta-react';

class LoginButton extends Component {
  state = {
    authenticated: null,
    user: null,
    menuAnchorEl: null,
  };

  componentDidUpdate() {
    this.checkAuthentication();
  }

  componentDidMount() {
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      const user = await this.props.auth.getUser();
      this.setState({ authenticated, user });
    }
  }

  login = () => this.props.auth.login();
  logout = () => {
    this.handleMenuClose();
    this.props.auth.logout();
  };

  handleMenuOpen = event => this.setState({ menuAnchorEl: event.currentTarget });
  handleMenuClose = () => this.setState({ menuAnchorEl: null });

  render() {
    const { authenticated, user, menuAnchorEl } = this.state;

    if (authenticated == null) return null;
    if (!authenticated) return Login;

    const menuPosition = {
      vertical: 'top',
      horizontal: 'right',
    };

    return (
      
        
          
        
        <Menu
          anchorEl={menuAnchorEl}
          anchorOrigin={menuPosition}
          transformOrigin={menuPosition}
          open={!!menuAnchorEl}
          onClose={this.handleMenuClose}
        >
          
            <ListItemText
              primary="Logout"
              secondary={user && user.name}
            />
          
        
      
    );
  }
}

export default withAuth(LoginButton);


React components have a concept of state management. Each component can be passed props (in a component like ``````, type and number would be considered props). They can also maintain their own state, which has some initial values and can be changed with a function called setState. Any time the props or state changes, the component will rerender, and if changes need to be made to the DOM they will happen then. In a component, you can access these with this.props or this.state, respectively.

Here, you’re creating a new React component and setting the initial state values. Until you query the auth prop, you don’t know whether there’s a user or not, so you set authenticated and user to null. Material UI will use menuAnchorEl to know where to anchor the menu that lets you log the user out.

class LoginButton extends Component {
  state = {
    authenticated: null,
    user: null,
    menuAnchorEl: null,
  };

  // ...
}


React components also have their own lifecycle methods, which are hooks you can use to trigger actions at certain stages of the component lifecycle. Here, when the component is first mounted you’ll check to see whether or not the user has been authenticated, and if so get some more details about the user, such as their name and email address. You also want to rerun this check whenever the component updates, but you need to be careful to only update the state when something is different, otherwise you’ll get yourself into an infinite loop (the component updates, so you give the component new values, which updates the component, you give it new values, etc.). The withAuth function is a Higher Order Component (HOC) which wraps the original component and returns another one containing the auth prop.

class LoginButton extends Component {
  // ...

  componentDidUpdate() {
    this.checkAuthentication();
  }

  componentDidMount() {
    this.checkAuthentication();
  }

  async checkAuthentication() {
    const authenticated = await this.props.auth.isAuthenticated();
    if (authenticated !== this.state.authenticated) {
      const user = await this.props.auth.getUser();
      this.setState({ authenticated, user });
    }
  }

  // ...
}

export default withAuth(LoginButton);


The following functions are helper functions used later to log the user in or out, and open or close the menu. Writing the function as an arrow function ensures that this is referring to the instantiation of the component. Without this, if a function is called somewhere outside of the component (e.g. in an onClick event), you would lose access to the component and wouldn’t be able to execute functions on it or access props or state.

class LoginButton extends Component {
  // ...

  login = () => this.props.auth.login();
  logout = () => {
    this.handleMenuClose();
    this.props.auth.logout();
  };

  handleMenuOpen = event => this.setState({ menuAnchorEl: event.currentTarget });
}


All React components must have a render() function. This is what tells React what to display on the screen, even if it shouldn’t display anything (in which case you can return null).

When you’re not sure of the authentication state yet, you can just return null so the button isn’t rendered at all. Once Okta this.props.auth.isAuthenticated() returns, the value will either be true or false. If it’s false, you’ll want to provide a Login button. If the user is logged in, you can instead display an avatar icon that has a dropdown menu with a Logout button.

class LoginButton extends Component {
  // ...

  render() {
    const { authenticated, user, menuAnchorEl } = this.state;

    if (authenticated == null) return null;
    if (!authenticated) return Login;

    const menuPosition = {
      vertical: &apos;top&apos;,
      horizontal: &apos;right&apos;,
    };

    return (
      
        
          
        
        <Menu
          anchorEl={menuAnchorEl}
          anchorOrigin={menuPosition}
          transformOrigin={menuPosition}
          open={!!menuAnchorEl}
          onClose={this.handleMenuClose}
        >
          
            <ListItemText
              primary="Logout"
              secondary={user && user.name}
            />
          
        
      
    );
  }
}


The next piece of the puzzle is to add this LoginButton component to your header. In order to display it on the right-hand side of the page, you can put an empty spacer div that has a flex value of 1. Since the other objects aren’t told to flex, the spacer will take up as much space as it can. Modify your src/components/AppHeader.js file like so:

src/components/AppHeader.js

--- a/src/components/AppHeader.js
+++ b/src/components/AppHeader.js
@@ -3,16 +3,27 @@ import {
   AppBar,
   Toolbar,
   Typography,
+  withStyles,
 } from &apos;@material-ui/core&apos;;

-const AppHeader = () => (
+import LoginButton from &apos;./LoginButton&apos;;
+
+const styles = {
+  flex: {
+    flex: 1,
+  },
+};
+
+const AppHeader = ({ classes }) => (
   
     
       
         My React App
       
+      
+      
     
   
 );

-export default AppHeader;
+export default withStyles(styles)(AppHeader);


You should now be able to log in and out of your app using the button in the top right.

When you click the Login button, you’ll be redirected to your Okta organization URL to handle authentication. You can log in with the same credentials you use in your developer console.

Once successfully signed in, you’re returned back to your app and should now see an icon showing that you’re logged in. If you click on the icon, you’ll see your name in a logout button. Clicking the button keeps you on the homepage but logs you out again.

Add a Node REST API Server

Now that users can securely authenticate, you can build the REST API server to perform CRUD operations on a post model. You’ll need to add quite a few dependencies to your project at this point:

yarn add @okta/[email protected] [email protected] [email protected] [email protected] [email protected] express @4.16.3 [email protected] [email protected]
yarn add -D [email protected]


Create a new folder for the server under the src directory:

mkdir src/server


Now create a new file src/server/index.js. To keep this simple we will just use a single file, but you could have a whole subtree of files in this folder. Keeping it in a separate folder lets you watch for changes just in this subdirectory and reload the server only when making changes to this file, instead of anytime any file in src changes. Again, I’ll post the whole file and then explain some key sections below.

src/server/index.js

require(&apos;dotenv&apos;).config({ path: &apos;.env.local&apos; });

const express = require(&apos;express&apos;);
const cors = require(&apos;cors&apos;);
const bodyParser = require(&apos;body-parser&apos;);
const Sequelize = require(&apos;sequelize&apos;);
const epilogue = require(&apos;epilogue&apos;);
const OktaJwtVerifier = require(&apos;@okta/jwt-verifier&apos;);

const oktaJwtVerifier = new OktaJwtVerifier({
  clientId: process.env.REACT_APP_OKTA_CLIENT_ID,
  issuer: `${process.env.REACT_APP_OKTA_ORG_URL}/oauth2/default`,
});

const app = express();
app.use(cors());
app.use(bodyParser.json());

app.use(async (req, res, next) => {
  try {
    if (!req.headers.authorization) throw new Error(&apos;Authorization header is required&apos;);

    const accessToken = req.headers.authorization.trim().split(&apos; &apos;)[1];
    await oktaJwtVerifier.verifyAccessToken(accessToken);
    next();
  } catch (error) {
    next(error.message);
  }
});

const database = new Sequelize({
  dialect: &apos;sqlite&apos;,
  storage: &apos;./test.sqlite&apos;,
});

const Post = database.define(&apos;posts&apos;, {
  title: Sequelize.STRING,
  body: Sequelize.TEXT,
});

epilogue.initialize({ app, sequelize: database });

epilogue.resource({
  model: Post,
  endpoints: [&apos;/posts&apos;, &apos;/posts/:id&apos;],
});

const port = process.env.SERVER_PORT || 3001;

database.sync().then(() => {
  app.listen(port, () => {
    console.log(`Listening on port ${port}`);
  });
});


The following loads the environment variables we used in the React app. This way we can use the same env variables, and only have to set them in one place.

require(&apos;dotenv&apos;).config({ path: &apos;.env.local&apos; });


This sets up the HTTP server and adds some settings to allow for Cross-Origin Resource Sharing (CORS) and will automatically parse JSON.

const app = express();
app.use(cors());
app.use(bodyParser.json());


Here is where you check that a user is properly authenticated. First, throw an error if there is no Authorizationheader, which is how you will send the authorization token. The token will actually look like Bearer aLongBase64String. You want to pass the Base 64 string to the Okta JWT Verifier to check that the user is properly authenticated. The verifier will initially send a request to the issuer to get a list of valid signatures, and will then check locally that the token is valid. On subsequent requests, this can be done locally unless it finds a claim that it doesn’t have signatures for yet.

If everything looks good, the call to next() tells Express to go ahead and continue processing the request. If however, the claim is invalid, an error will be thrown. The error is then passed into next to tell Express that something went wrong. Express will then send an error back to the client instead of proceeding.

app.use(async (req, res, next) => {
  try {
    if (!req.headers.authorization) throw new Error(&apos;Authorization header is required&apos;);

    const accessToken = req.headers.authorization.trim().split(&apos; &apos;)[1];
    await oktaJwtVerifier.verifyAccessToken(accessToken);
    next();
  } catch (error) {
    next(error.message);
  }
});


Here is where you set up Sequelize. This is a quick way of creating database models. You can Sequelize with a wide variety of databases, but here you can just use SQLite to get up and running quickly without any other dependencies.

const database = new Sequelize({
  dialect: &apos;sqlite&apos;,
  storage: &apos;./test.sqlite&apos;,
});

const Post = database.define(&apos;posts&apos;, {
  title: Sequelize.STRING,
  body: Sequelize.TEXT,
});


Epilogue works well with Sequelize and Express. It binds the two together like glue, creating a set of CRUD endpoints with just a couple lines of code. First, you initialize Epilogue with the Express app and the Sequelize database model. Next, you tell it to create your endpoints for the Post model: one for a list of posts, which will have POST and GETmethods; and one for individual posts, which will have GET, PUT, and DELETE methods.

epilogue.initialize({ app, sequelize: database });

epilogue.resource({
  model: Post,
  endpoints: [&apos;/posts&apos;, &apos;/posts/:id&apos;],
});


The last part of the server is where you tell Express to start listening for HTTP requests. You need to tell sequelize to initialize the database, and when it’s done it’s OK for Express to start listening on the port you decide. By default, since the React app is using 3000, we’ll just add one to make it port 3001.

const port = process.env.SERVER_PORT || 3001;

database.sync().then(() => {
  app.listen(port, () => {
    console.log(`Listening on port ${port}`);
  });
});


Now you can make a couple small changes to package.json to make it easier to run both the frontend and backend at the same time. Replace the default start script and add a couple others, so your scripts section looks like this:

package.json

  "scripts": {
    "start": "npm-run-all --parallel watch:server start:web",
    "start:web": "react-scripts start",
    "start:server": "node src/server",
    "watch:server": "nodemon --watch src/server src/server",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }


Now you can simply run yarn start and both the server and the React app will run at the same time, reloading whenever relevant changes are made. If you need to change the port for any reason, you can change the React app’s port and the server’s port with the PORT and SERVER_PORT environment variables, respectively. For example, PORT=8080 SERVER_PORT=8081 yarn start.

Add the Posts Manager Page to Your Node + React App

Now that you have a Node backend to manage your posts, you can link up the React frontend by adding another page. This will send requests to fetch, create, edit, and delete posts. It will also send the required authorization token along with each request so the server knows that you’re a valid user.

One nice thing about React Router is that it lets you use variables in the URL. This will allow us to use the ID of a post in the URL, so you could go to /posts/2 to view post number 2. With that in mind, you can create a modal that will be open whenever you are on that portion of the page, and to close the modal all you would need to do is navigate back to /posts.

Forms in React can be a bit of a pain. You can use a basic form element, but you would also need to listen for onChange events, update the state of the component, and set the new value on the input elements. To make forms easier, there are at least a few libraries out there, but I’ll show you how to use React Final Form to cut out a lot of the boilerplate.

You’ll also need recompose, lodash, and moment for some helper functions. You can install them all as dependencies with the following command:

yarn add [email protected] [email protected] [email protected] [email protected] [email protected]


Create a Post Editor Component

Create a PostEditor component which will be used in the Post Manager page. For now, the posts will just have title and body fields.

src/components/PostEditor.js

import React from &apos;react&apos;;
import {
  withStyles,
  Card,
  CardContent,
  CardActions,
  Modal,
  Button,
  TextField,
} from &apos;@material-ui/core&apos;;
import { compose } from &apos;recompose&apos;;
import { withRouter } from &apos;react-router-dom&apos;;
import { Form, Field } from &apos;react-final-form&apos;;

const styles = theme => ({
  modal: {
    display: &apos;flex&apos;,
    alignItems: &apos;center&apos;,
    justifyContent: &apos;center&apos;,
  },
  modalCard: {
    width: &apos;90%&apos;,
    maxWidth: 500,
  },
  modalCardContent: {
    display: &apos;flex&apos;,
    flexDirection: &apos;column&apos;,
  },
  marginTop: {
    marginTop: 2 * theme.spacing.unit,
  },
});

const PostEditor = ({ classes, post, onSave, history }) => (
  
    {({ handleSubmit }) => (
      <Modal
        className={classes.modal}
        onClose={() => history.goBack()}
        open
      >
        
          
            
              
                {({ input }) => }
              
              
                {({ input }) => (
                  <TextField
                    className={classes.marginTop}
                    label="Body"
                    multiline
                    rows={4}
                    {...input}
                  />
                )}
              
            
            
              Save
               history.goBack()}>Cancel
            
          
        
      
    )}
  
);

export default compose(
  withRouter,
  withStyles(styles),
)(PostEditor);


Create the Posts Manager Page Component

You’ll also need a page to render a list of posts, and to inject the post editor. Create a new file src/pages/PostsManager.js. Once again, I’ll post the whole file then walk you through each section.

src/pages/PostsManager.js

import React, { Component, Fragment } from &apos;react&apos;;
import { withAuth } from &apos;@okta/okta-react&apos;;
import { withRouter, Route, Redirect, Link } from &apos;react-router-dom&apos;;
import {
  withStyles,
  Typography,
  Button,
  IconButton,
  Paper,
  List,
  ListItem,
  ListItemText,
  ListItemSecondaryAction,
} from &apos;@material-ui/core&apos;;
import { Delete as DeleteIcon, Add as AddIcon } from &apos;@material-ui/icons&apos;;
import moment from &apos;moment&apos;;
import { find, orderBy } from &apos;lodash&apos;;
import { compose } from &apos;recompose&apos;;

import PostEditor from &apos;../components/PostEditor&apos;;

const styles = theme => ({
  posts: {
    marginTop: 2 * theme.spacing.unit,
  },
  fab: {
    position: &apos;absolute&apos;,
    bottom: 3 * theme.spacing.unit,
    right: 3 * theme.spacing.unit,
    [theme.breakpoints.down(&apos;xs&apos;)]: {
      bottom: 2 * theme.spacing.unit,
      right: 2 * theme.spacing.unit,
    },
  },
});

const API = process.env.REACT_APP_API || &apos;http://localhost:3001&apos;;

class PostsManager extends Component {
  state = {
    loading: true,
    posts: [],
  };

  componentDidMount() {
    this.getPosts();
  }

  async fetch(method, endpoint, body) {
    try {
      const response = await fetch(`${API}${endpoint}`, {
        method,
        body: body && JSON.stringify(body),
        headers: {
          &apos;content-type&apos;: &apos;application/json&apos;,
          accept: &apos;application/json&apos;,
          authorization: `Bearer ${await this.props.auth.getAccessToken()}`,
        },
      });
      return await response.json();
    } catch (error) {
      console.error(error);
    }
  }

  async getPosts() {
    this.setState({ loading: false, posts: await this.fetch(&apos;get&apos;, &apos;/posts&apos;) });
  }

  savePost = async (post) => {
    if (post.id) {
      await this.fetch(&apos;put&apos;, `/posts/${post.id}`, post);
    } else {
      await this.fetch(&apos;post&apos;, &apos;/posts&apos;, post);
    }

    this.props.history.goBack();
    this.getPosts();
  }

  async deletePost(post) {
    if (window.confirm(`Are you sure you want to delete "${post.title}"`)) {
      await this.fetch(&apos;delete&apos;, `/posts/${post.id}`);
      this.getPosts();
    }
  }

  renderPostEditor = ({ match: { params: { id } } }) => {
    if (this.state.loading) return null;
    const post = find(this.state.posts, { id: Number(id) });

    if (!post && id !== &apos;new&apos;) return ;

    return ;
  };

  render() {
    const { classes } = this.props;

    return (
      
        Posts Manager
        {this.state.posts.length > 0 ? (
          
            
              {orderBy(this.state.posts, [&apos;updatedAt&apos;, &apos;title&apos;], [&apos;desc&apos;, &apos;asc&apos;]).map(post => (
                
                  <ListItemText
                    primary={post.title}
                    secondary={post.updatedAt && `Updated ${moment(post.updatedAt).fromNow()}`}
                  />
                  
                     this.deletePost(post)} color="inherit">
                      ~~
                    ~~
                  
                
              ))}
            
          
        ) : (
          !this.state.loading && No posts to display
        )}
        <Button
          variant="fab"
          color="secondary"
          aria-label="add"
          className={classes.fab}
          component={Link}
          to="/posts/new"
        >
          
        
        
      
    );
  }
}

export default compose(
  withAuth,
  withRouter,
  withStyles(styles),
)(PostsManager);


The backend is set to run on port 3001 on your local machine by default, so this sets that as a fallback. However, if you’d like to run this on another server, or on another port, you’ll need a way to edit that. You could run the app with API=[https://api.example.com](https://api.example.com "https://api.example.com") yarn start:web to override this.

const API = process.env.REACT_APP_API || &apos;http://localhost:3001&apos;;


When the component first mounts, you won’t have any data yet. You may want some indicator that the page is still loading, so setting the state to loading: true lets you know that later on. Setting the initial posts to an empty array makes the code simpler later since you can just always assume you have an array, even if it’s empty. Then you’ll want to fetch the set of posts as soon as the component mounts.

class PostsManager extends Component {
  state = {
    loading: true,
    posts: [],
  };

  componentDidMount() {
    this.getPosts();
  }

  // ...
}


Here you’re setting up a simple helper function to send a request to the server. This uses the fetch function that’s built into all modern browsers. The helper accepts a method (e.g. get, post, delete), an endpoint (here it would either be /posts or a specific post like /posts/3), and a body (some optional JSON value, in this case the post content).

This also sets some headers to tell the backend that any body it sends will be in JSON format, and it sets the authorization header by fetching the access token from Okta.

class PostsManager extends Component {
  // ...

  async fetch(method, endpoint, body) {
    try {
      const response = await fetch(`${API}${endpoint}`, {
        method,
        body: body && JSON.stringify(body),
        headers: {
          &apos;content-type&apos;: &apos;application/json&apos;,
          accept: &apos;application/json&apos;,
          authorization: `Bearer ${await this.props.auth.getAccessToken()}`,
        },
      });
      return await response.json();
    } catch (error) {
      console.error(error);
    }
  }

  // ...
}


Here is where you call the fetch helper function.

You have one function to fetch posts (getPosts), which will also set loading to false since it’s the function that gets called when the component first loads.

There’s another function to save posts, which handles the case of adding a new post as well as modifying an existing post. Since the posts will be loaded in a modal based on the route, once the post is updated the browser is told to go back to /posts.

The last function is to delete a post. The confirm function actually blocks the UI, so it’s not normally recommended for an app like this, but it works well for demo purposes. It’s a built-in browser function that simply gives a popup asking you to confirm, and returns either true or false depending on your answer.

After saving or deleting a post, the getPosts command is called again to make sure that all the posts are up to date.

class PostsManager extends Component {
  // ...

  async getPosts() {
    this.setState({ loading: false, posts: await this.fetch(&apos;get&apos;, &apos;/posts&apos;) });
  }

  savePost = async (post) => {
    if (post.id) {
      await this.fetch(&apos;put&apos;, `/posts/${post.id}`, post);
    } else {
      await this.fetch(&apos;post&apos;, &apos;/posts&apos;, post);
    }

    this.props.history.goBack();
    this.getPosts();
  }

  async deletePost(post) {
    if (window.confirm(`Are you sure you want to delete "${post.title}"`)) {
      await this.fetch(&apos;delete&apos;, `/posts/${post.id}`);
      this.getPosts();
    }
  }

  // ...
}


The renderPostEditor function will be passed into a Route so that it only renders when you’re looking at a specific post. If you’re still loading posts, you won’t want to render anything just yet, so you can just return null. After the posts are loaded, you can use the id param to look for a post that matches. If you don’t find one for some reason, you should redirect back to the /posts page, since it’s likely a bad URL (maybe that post was already deleted).

The only exception is for a special route /posts/new, which will be used to create a new post. In that case, you don’t want to redirect. Now that you have a post model, you can render the PostEditor component from above and pass the model to it to render in a modal.

class PostsManager extends Component {
  // ...

  renderPostEditor = ({ match: { params: { id } } }) => {
    if (this.state.loading) return null;
    const post = find(this.state.posts, { id: Number(id) });

    if (!post && id !== &apos;new&apos;) return ;

    return ;
  };

  // ...
}


Here is the main render function. When there are no posts, it should display a message “No posts to display”, except when the posts are still loading. You could choose to render a loading symbol, but for now just rendering nothing will suffice.

When there are posts, it renders a simple list of them, with the main text being the title of the post, and some subtext saying when it was last updated. The updated text uses moment for rendering a user-friendly string like 10 minutes ago instead of the raw timestamp.

By adding component={Link} and the to value, you are actually turning the list item into a link that takes you to the path of the post (e.g. /posts/5). You can do the same to send you to create a new post, by creating the Floating Action Button (FAB) that you see on many Material Design apps.

class PostsManager extends Component {
  // ...

  render() {
    const { classes } = this.props;

    return (
      
        Posts Manager
        {this.state.posts.length > 0 ? (
          
            
              {orderBy(this.state.posts, [&apos;updatedAt&apos;, &apos;title&apos;], [&apos;desc&apos;, &apos;asc&apos;]).map(post => (
                
                  <ListItemText
                    primary={post.title}
                    secondary={post.updatedAt && `Updated ${moment(post.updatedAt).fromNow()}`}
                  />
                  
                     this.deletePost(post)} color="inherit">
                      ~~
                    ~~
                  
                
              ))}
            
          
        ) : (
          !this.state.loading && No posts to display
        )}
        <Button
          variant="fab"
          color="secondary"
          aria-label="add"
          className={classes.fab}
          component={Link}
          to="/posts/new"
        >
          
        
        
      
    );
  }
}


In order to get access to the Okta SDK, you need to use the withAuth HOC again. This time there are actually a few other HOCs to add, so you can use a utility function called compose from to wrap your component with multiple HOCs.

export default compose(
  withAuth,
  withRouter,
  withStyles(styles),
)(PostsManager);


Add the Route and Navigation Links

OK, you’re in the home stretch now. You just need to tell the app when to render the Posts Manager page, and a link to get there.

Add the PostsManager page to src/App.js. Okta provides a SecureRoute component which is an extension of React Router’s Route component. This will ensure that if you try to go to that page and aren’t logged in, you’ll be redirected to sign in. If you’re on that page and you sign out, you’ll be redirected home.

src/App.js

--- a/src/App.js
+++ b/src/App.js
@@ -1,6 +1,6 @@
 import React, { Fragment } from &apos;react&apos;;
 import { Route } from &apos;react-router-dom&apos;;
-import { ImplicitCallback } from &apos;@okta/okta-react&apos;;
+import { SecureRoute, ImplicitCallback } from &apos;@okta/okta-react&apos;;
 import {
   CssBaseline,
   withStyles,
@@ -8,6 +8,7 @@ import {

 import AppHeader from &apos;./components/AppHeader&apos;;
 import Home from &apos;./pages/Home&apos;;
+import PostsManager from &apos;./pages/PostsManager&apos;;

 const styles = theme => ({
   main: {
@@ -24,6 +25,7 @@ const App = ({ classes }) => (
     
     
       
+      
       
     
   


You also need to add a couple links to get to the Posts Manager and back to the Home page. You can do this in the App Header component you made earlier.

src/components/AppHeader.js

--- a/src/components/AppHeader.js
+++ b/src/components/AppHeader.js
@@ -1,6 +1,8 @@
 import React from &apos;react&apos;;
+import { Link } from &apos;react-router-dom&apos;;
 import {
   AppBar,
+  Button,
   Toolbar,
   Typography,
   withStyles,
@@ -20,6 +22,8 @@ const AppHeader = ({ classes }) => (
       
         My React App
       
+      Home
+      Posts Manager
       
       
     


Test Your React + Node CRUD App

You now have a fully functioning Single Page App, connected to a REST API server, secured with authentication via Okta’s OIDC.

Go ahead and test out the app now. If they’re not already running, make sure to start the server and the frontend. In your terminal run yarn start from your project directory.

Navigate to [http://localhost:3000](http://localhost:3000 "http://localhost:3000"). You should be able to add, edit, view, and delete posts to your heart’s desire!

Learn More About React, Node, and Okta

Hopefully you found this article helpful. If you’re new to React, maybe you’re one step closer to deciding whether you love it or hate it. If you’re a React veteran, maybe you found out how easy it can be to add authentication to a new or existing app. Or maybe you learned a bit about Node.

How to Use Express.js, Node.js and MongoDB.js

How to Use Express.js, Node.js and MongoDB.js

In this post, I will show you how to use Express.js, Node.js and MongoDB.js. We will be creating a very simple Node application, that will allow users to input data that they want to store in a MongoDB database. It will also show all items that have been entered into the database.

In this post, I will show you how to use Express.js, Node.js and MongoDB.js. We will be creating a very simple Node application, that will allow users to input data that they want to store in a MongoDB database. It will also show all items that have been entered into the database.

Creating a Node Application

To get started I would recommend creating a new database that will contain our application. For this demo I am creating a directory called node-demo. After creating the directory you will need to change into that directory.

mkdir node-demo
cd node-demo

Once we are in the directory we will need to create an application and we can do this by running the command
npm init

This will ask you a series of questions. Here are the answers I gave to the prompts.

The first step is to create a file that will contain our code for our Node.js server.

touch app.js

In our app.js we are going to add the following code to build a very simple Node.js Application.

var express = require("express");
var app = express();
var port = 3000;
 
app.get("/", (req, res) => {
&nbsp;&nbsp;res.send("Hello World");
});
 
app.listen(port, () => {
  console.log("Server listening on port " + port);
});

What the code does is require the express.js application. It then creates app by calling express. We define our port to be 3000.

The app.use line will listen to requests from the browser and will return the text “Hello World” back to the browser.

The last line actually starts the server and tells it to listen on port 3000.

Installing Express

Our app.js required the Express.js module. We need to install express in order for this to work properly. Go to your terminal and enter this command.

npm install express --save

This command will install the express module into our package.json. The module is installed as a dependency in our package.json as shown below.

To test our application you can go to the terminal and enter the command

node app.js

Open up a browser and navigate to the url http://localhost:3000

You will see the following in your browser

Creating Website to Save Data to MongoDB Database

Instead of showing the text “Hello World” when people view your application, what we want to do is to show a place for user to save data to the database.

We are going to allow users to enter a first name and a last name that we will be saving in the database.

To do this we will need to create a basic HTML file. In your terminal enter the following command to create an index.html file.

touch index.html

In our index.html file we will be creating an input filed where users can input data that they want to have stored in the database. We will also need a button for users to click on that will add the data to the database.

Here is what our index.html file looks like.

<!DOCTYPE html>
<html>
  <head>
    <title>Intro to Node and MongoDB<title>
  <head>

  <body>
    <h1>Into to Node and MongoDB<&#47;h1>
    <form method="post" action="/addname">
      <label>Enter Your Name<&#47;label><br>
      <input type="text" name="firstName" placeholder="Enter first name..." required>
      <input type="text" name="lastName" placeholder="Enter last name..." required>
      <input type="submit" value="Add Name">
    </form>
  <body>
<html>

If you are familiar with HTML, you will not find anything unusual in our code for our index.html file. We are creating a form where users can input their first name and last name and then click an “Add Name” button.

The form will do a post call to the /addname endpoint. We will be talking about endpoints and post later in this tutorial.

Displaying our Website to Users

We were previously displaying the text “Hello World” to users when they visited our website. Now we want to display our html file that we created. To do this we will need to change the app.use line our our app.js file.

We will be using the sendFile command to show the index.html file. We will need to tell the server exactly where to find the index.html file. We can do that by using a node global call __dirname. The __dirname will provide the current directly where the command was run. We will then append the path to our index.html file.

The app.use lines will need to be changed to
app.use("/", (req, res) => {   res.sendFile(__dirname + "/index.html"); });

Once you have saved your app.js file, we can test it by going to terminal and running node app.js

Open your browser and navigate to “http://localhost:3000”. You will see the following

Connecting to the Database

Now we need to add our database to the application. We will be connecting to a MongoDB database. I am assuming that you already have MongoDB installed and running on your computer.

To connect to the MongoDB database we are going to use a module called Mongoose. We will need to install mongoose module just like we did with express. Go to your terminal and enter the following command.
npm install mongoose --save

This will install the mongoose model and add it as a dependency in our package.json.

Connecting to the Database

Now that we have the mongoose module installed, we need to connect to the database in our app.js file. MongoDB, by default, runs on port 27017. You connect to the database by telling it the location of the database and the name of the database.

In our app.js file after the line for the port and before the app.use line, enter the following two lines to get access to mongoose and to connect to the database. For the database, I am going to use “node-demo”.

var mongoose = require("mongoose"); mongoose.Promise = global.Promise; mongoose.connect("mongodb://localhost:27017/node-demo");

Creating a Database Schema

Once the user enters data in the input field and clicks the add button, we want the contents of the input field to be stored in the database. In order to know the format of the data in the database, we need to have a Schema.

For this tutorial, we will need a very simple Schema that has only two fields. I am going to call the field firstName and lastName. The data stored in both fields will be a String.

After connecting to the database in our app.js we need to define our Schema. Here are the lines you need to add to the app.js.
var nameSchema = new mongoose.Schema({   firstName: String,   lastNameName: String });

Once we have built our Schema, we need to create a model from it. I am going to call my model “DataInput”. Here is the line you will add next to create our mode.
var User = mongoose.model("User", nameSchema);

Creating RESTful API

Now that we have a connection to our database, we need to create the mechanism by which data will be added to the database. This is done through our REST API. We will need to create an endpoint that will be used to send data to our server. Once the server receives this data then it will store the data in the database.

An endpoint is a route that our server will be listening to to get data from the browser. We already have one route that we have created already in the application and that is the route that is listening at the endpoint “/” which is the homepage of our application.

HTTP Verbs in a REST API

The communication between the client(the browser) and the server is done through an HTTP verb. The most common HTTP verbs are
GET, PUT, POST, and DELETE.

The following table explains what each HTTP verb does.

HTTP Verb Operation
GET Read
POST Create
PUT Update
DELETE Delete

As you can see from these verbs, they form the basis of CRUD operations that I talked about previously.

Building a CRUD endpoint

If you remember, the form in our index.html file used a post method to call this endpoint. We will now create this endpoint.

In our previous endpoint we used a “GET” http verb to display the index.html file. We are going to do something very similar but instead of using “GET”, we are going to use “POST”. To get started this is what the framework of our endpoint will look like.

app.post("/addname", (req, res) => {
 
});
Express Middleware

To fill out the contents of our endpoint, we want to store the firstName and lastName entered by the user into the database. The values for firstName and lastName are in the body of the request that we send to the server. We want to capture that data, convert it to JSON and store it into the database.

Express.js version 4 removed all middleware. To parse the data in the body we will need to add middleware into our application to provide this functionality. We will be using the body-parser module. We need to install it, so in your terminal window enter the following command.

npm install body-parser --save

Once it is installed, we will need to require this module and configure it. The configuration will allow us to pass the data for firstName and lastName in the body to the server. It can also convert that data into JSON format. This will be handy because we can take this formatted data and save it directly into our database.

To add the body-parser middleware to our application and configure it, we can add the following lines directly after the line that sets our port.

var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
Saving data to database

Mongoose provides a save function that will take a JSON object and store it in the database. Our body-parser middleware, will convert the user’s input into the JSON format for us.

To save the data into the database, we need to create a new instance of our model that we created early. We will pass into this instance the user’s input. Once we have it then we just need to enter the command “save”.

Mongoose will return a promise on a save to the database. A promise is what is returned when the save to the database completes. This save will either finish successfully or it will fail. A promise provides two methods that will handle both of these scenarios.

If this save to the database was successful it will return to the .then segment of the promise. In this case we want to send text back the user to let them know the data was saved to the database.

If it fails it will return to the .catch segment of the promise. In this case, we want to send text back to the user telling them the data was not saved to the database. It is best practice to also change the statusCode that is returned from the default 200 to a 400. A 400 statusCode signifies that the operation failed.

Now putting all of this together here is what our final endpoint will look like.

app.post("/addname", (req, res) => {
  var myData = new User(req.body);
  myData.save()
    .then(item => {
      res.send("item saved to database");
    })
    .catch(err => {
      res.status(400).send("unable to save to database");
    });
});
Testing our code

Save your code. Go to your terminal and enter the command node app.js to start our server. Open up your browser and navigate to the URL “http://localhost:3000”. You will see our index.html file displayed to you.

Make sure you have mongo running.

Enter your first name and last name in the input fields and then click the “Add Name” button. You should get back text that says the name has been saved to the database like below.

Access to Code

The final version of the code is available in my Github repo. To access the code click here. Thank you for reading !

Node.js for Beginners - Learn Node.js from Scratch (Step by Step)

Node.js for Beginners - Learn Node.js from Scratch (Step by Step)

Node.js for Beginners - Learn Node.js from Scratch (Step by Step) - Learn the basics of Node.js. This Node.js tutorial will guide you step by step so that you will learn basics and theory of every part. Learn to use Node.js like a professional. You’ll learn: Basic Of Node, Modules, NPM In Node, Event, Email, Uploading File, Advance Of Node.

Node.js for Beginners

Learn Node.js from Scratch (Step by Step)

Welcome to my course "Node.js for Beginners - Learn Node.js from Scratch". This course will guide you step by step so that you will learn basics and theory of every part. This course contain hands on example so that you can understand coding in Node.js better. If you have no previous knowledge or experience in Node.js, you will like that the course begins with Node.js basics. otherwise if you have few experience in programming in Node.js, this course can help you learn some new information . This course contain hands on practical examples without neglecting theory and basics. Learn to use Node.js like a professional. This comprehensive course will allow to work on the real world as an expert!
What you’ll learn:

  • Basic Of Node
  • Modules
  • NPM In Node
  • Event
  • Email
  • Uploading File
  • Advance Of Node

Top 7 Most Popular Node.js Frameworks You Should Know

Top 7 Most Popular Node.js Frameworks You Should Know

Node.js is an open-source, cross-platform, runtime environment that allows developers to run JavaScript outside of a browser. In this post, you'll see top 7 of the most popular Node frameworks at this point in time (ranked from high to low by GitHub stars).

Node.js is an open-source, cross-platform, runtime environment that allows developers to run JavaScript outside of a browser.

One of the main advantages of Node is that it enables developers to use JavaScript on both the front-end and the back-end of an application. This not only makes the source code of any app cleaner and more consistent, but it significantly speeds up app development too, as developers only need to use one language.

Node is fast, scalable, and easy to get started with. Its default package manager is npm, which means it also sports the largest ecosystem of open-source libraries. Node is used by companies such as NASA, Uber, Netflix, and Walmart.

But Node doesn't come alone. It comes with a plethora of frameworks. A Node framework can be pictured as the external scaffolding that you can build your app in. These frameworks are built on top of Node and extend the technology's functionality, mostly by making apps easier to prototype and develop, while also making them faster and more scalable.

Below are 7of the most popular Node frameworks at this point in time (ranked from high to low by GitHub stars).

Express

With over 43,000 GitHub stars, Express is the most popular Node framework. It brands itself as a fast, unopinionated, and minimalist framework. Express acts as middleware: it helps set up and configure routes to send and receive requests between the front-end and the database of an app.

Express provides lightweight, powerful tools for HTTP servers. It's a great framework for single-page apps, websites, hybrids, or public HTTP APIs. It supports over fourteen different template engines, so developers aren't forced into any specific ORM.

Meteor

Meteor is a full-stack JavaScript platform. It allows developers to build real-time web apps, i.e. apps where code changes are pushed to all browsers and devices in real-time. Additionally, servers send data over the wire, instead of HTML. The client renders the data.

The project has over 41,000 GitHub stars and is built to power large projects. Meteor is used by companies such as Mazda, Honeywell, Qualcomm, and IKEA. It has excellent documentation and a strong community behind it.

Koa

Koa is built by the same team that built Express. It uses ES6 methods that allow developers to work without callbacks. Developers also have more control over error-handling. Koa has no middleware within its core, which means that developers have more control over configuration, but which means that traditional Node middleware (e.g. req, res, next) won't work with Koa.

Koa already has over 26,000 GitHub stars. The Express developers built Koa because they wanted a lighter framework that was more expressive and more robust than Express. You can find out more about the differences between Koa and Express here.

Sails

Sails is a real-time, MVC framework for Node that's built on Express. It supports auto-generated REST APIs and comes with an easy WebSocket integration.

The project has over 20,000 stars on GitHub and is compatible with almost all databases (MySQL, MongoDB, PostgreSQL, Redis). It's also compatible with most front-end technologies (Angular, iOS, Android, React, and even Windows Phone).

Nest

Nest has over 15,000 GitHub stars. It uses progressive JavaScript and is built with TypeScript, which means it comes with strong typing. It combines elements of object-oriented programming, functional programming, and functional reactive programming.

Nest is packaged in such a way it serves as a complete development kit for writing enterprise-level apps. The framework uses Express, but is compatible with a wide range of other libraries.

LoopBack

LoopBack is a framework that allows developers to quickly create REST APIs. It has an easy-to-use CLI wizard and allows developers to create models either on their schema or dynamically. It also has a built-in API explorer.

LoopBack has over 12,000 GitHub stars and is used by companies such as GoDaddy, Symantec, and the Bank of America. It's compatible with many REST services and a wide variety of databases (MongoDB, Oracle, MySQL, PostgreSQL).

Hapi

Similar to Express, hapi serves data by intermediating between server-side and client-side. As such, it's can serve as a substitute for Express. Hapi allows developers to focus on writing reusable app logic in a modular and prescriptive fashion.

The project has over 11,000 GitHub stars. It has built-in support for input validation, caching, authentication, and more. Hapi was originally developed to handle all of Walmart's mobile traffic during Black Friday.