Difference between revisions of "Creating Admin Portal Project in React"

From Logic Wiki
Jump to: navigation, search
 
Line 191: Line 191:
 
       <label htmlFor={name}>{label}</label>
 
       <label htmlFor={name}>{label}</label>
 
       <input
 
       <input
         id={name}
+
         id={name}`
 
         name={name}
 
         name={name}
 
         type="text"
 
         type="text"
Line 207: Line 207:
  
 
</pre>
 
</pre>
==== loginFormjsx ====
+
==== loginForm.jsx ====
 
<pre class="brush:js;">
 
<pre class="brush:js;">
 
import React, { Component } from "react";
 
import React, { Component } from "react";

Latest revision as of 14:47, 28 December 2018


Starting a project

Setting Up The Environment

  • install node
  • install create-react-app
npm i -g create-react-app

install VS Code

  • install VS Code
  • install VS Code snippets - Click Extensions icon on the left sidebar and search and install
    • Simple React Snippets by Burke Holland
    • Prettier by Esben Petersen
      • Set Format on Save
    • Auto Import by Sergey Korenuk

in VS Code go to File / Preferences / Settings and add the line below in UserSettings section

 "editor.formatOnSave":true

Creating React App

Go to the project folder

npx create-react-app adminportal
cd adminportal

adminportal is lowercase because [Create React App] doesn't like capitals

Installing Bootstrap

npm i bootstrap@4.1.1

go to ./src/index.js and add this line

import 'bootstrap/dist/css/bootstrap.css';

Install reactstrap

npm install --save reactstrap

Check it's site for more details

https://reactstrap.github.io/

Installing & Using FontAwesome Icons

npm i --save @fortawesome/fontawesome-svg-core 
npm i --save @fortawesome/free-solid-svg-icons 
npm i --save @fortawesome/react-fontawesome

Then in your app, import and add an icon to the Library:App.js

import { library } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faIgloo } from '@fortawesome/free-solid-svg-icons'

library.add(faIgloo)

Lastly, use the component and icon in your JSX:

 import React from 'react'
 import { faSearch } from "@fortawesome/free-solid-svg-icons";
 import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
 
 export const Food = () => (
  <div>
     <FontAwesomeIcon icon={faSearch} />
  </div>
 )

https://scotch.io/tutorials/using-font-awesome-5-with-react

Install nodemon

it restarts the application when file contents changes.

npm install --save-dev nodemon

Usage

npx nodemon index.js

Coding

Routing

install router

npm i react-router-dom

in index.js file add this line

import { BrowserRouter } from "react-router-dom";

and wrap <App/> with <BrowserRouter> like below

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);

in App.js import Route & Switch

import { Route, Switch } from "react-router-dom";

and add these lines to render()

    return (
      <div className="App">
        <TopBar />
        <SideBar />
        <header className="App-header">
          <div className="content">
            <Switch>
              <Route path="/admin" component={Admin} />
            </Switch>
          </div>
        </header>
      </div>
    );

So in this scenario there is one top bar and a left side bar. They are static. The rest of the screen (div with className="content") will be different in every page.

Switch is for stopping rendering to go to next Route which matches the satisfying criteria. Like:

if the first route is path="/admin" and the second route is "/" without a switch here it will render both of them back to back.

Links

In sideBar component when I click a link it normalyy reload the whole page as it uses <a> tag to prevent this import Link

import {Link} from "react-router-dom";

and replace <a with <Link and href with to. ie:

<Link to="/product">

Http Client - Preparation

install Axios

npm i axios

install Toastify

npm i react-toastify

in app.js import Toastfy and css file and add a tag for container

import {ToastContainer} from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

 render() {
   return (
       <ToastContainer/>
....

Creating httpService.js

create a folder "services" and within this folder create a file names "httpService.js"

import axios from "axios";
import { toast } from "react-toastify";
import log from "./logService.js";

axios.interceptors.response.use(null, error => {
  const expectedError =
    error.response &&
    error.response.status >= 400 &&
    error.response.status < 500;
  if (!expectedError) {
    logger.log(error);
    toast.error("An unexpected error occured.");
  }

  return Promise.reject(error);
});

export default {
  get: axios.get,
  post: axios.post,
  put: axios.put,
  delete: axios.delete
};

here we use interceptor for responses and capture any unexpected errors. display them in a toaster and send a copy to logService which is basically doing nothing at the moment.

logService

function init() {}

function log(error) {
  console.log(error);
}

export default {
  init,
  log
};

It is not functional but keep it as a placeholder for future.

Config.json

create a config.json file in the root to keep config elements in it. ie :

{
  "loginApiEndpoint": "http://localhost:10795",
  "apiEndpoint": "http://localhost:20795"
}


Authentication & Authorisation

Login Form

input.jsx

Instead of repeating input fields and validations etc. we can create an input component and reuse it when we need it.

  1. create a folder common
  2. create a file input.jsx

The content of input.jsx is

import React from "react";

const Input = ({ name, label, value, error, onChange }) => {
  return (
    <div className="form-group">
      <label htmlFor={name}>{label}</label>
      <input
        id={name}`
        name={name}
        type="text"
        className="form-control"
        autoFocus
        onChange={onChange}
        value={value}
      />
      {error && <div className="alert alert-danger">{error}</div>}
    </div>
  );
};

export default Input;

loginForm.jsx

import React, { Component } from "react";
import "./loginForm.css";
import Input from "../common/input";


Authentication Service

Create "authService.js" in the services folder

import http from "./httpService";
import { loginApiEndpoint } from "../config.json"

const apiEndpoint = loginApiEndpoint + "/api/Login";

export function login(email, password) { 
    return http.post(apiEndpoint, {Email:email, Password:password, Group:"Administrator"})
}