Difference between revisions of "Creating Admin Portal Project in React"
| (2 intermediate revisions by the same user not shown) | |||
| Line 163: | Line 163: | ||
</pre> | </pre> | ||
| + | It is not functional but keep it as a placeholder for future. | ||
| + | |||
=== Config.json === | === Config.json === | ||
create a config.json file in the root to keep config elements in it. ie : | create a config.json file in the root to keep config elements in it. ie : | ||
| Line 175: | Line 177: | ||
== Authentication & Authorisation == | == 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. | ||
| + | # create a folder '''common''' | ||
| + | # create a file '''input.jsx''' | ||
| + | The content of input.jsx is | ||
| + | <pre class="brush:js;"> | ||
| + | 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; | ||
| + | |||
| + | </pre> | ||
| + | ==== loginForm.jsx ==== | ||
| + | <pre class="brush:js;"> | ||
| + | import React, { Component } from "react"; | ||
| + | import "./loginForm.css"; | ||
| + | import Input from "../common/input"; | ||
| + | |||
| + | |||
| + | </pre> | ||
| + | === Authentication Service === | ||
Create "'''authService.js'''" in the '''services''' folder | Create "'''authService.js'''" in the '''services''' folder | ||
<pre class="brush:js;"> | <pre class="brush:js;"> | ||
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
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.
- create a folder common
- 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"})
}