Step 1
create reducer user
import { createSlice } from '@reduxjs/toolkit';
let initialState = {
email: '',
login_token: '',
isAuthenticated: false
};
export const user = createSlice({
name: 'user',
initialState,
reducers: {
login: (state, actions) => {
return (state = actions.payload);
},
logout: (state) => {
return (state = initialState);
}
}
});
export const { login, logout } = user.actions;
export default user.reducer;
Step 2
create store
import pageReducer from '../reducer/page';
import modalReducer from '../reducer/modal';
import userReducer from '../reducer/user';
import { configureStore } from '@reduxjs/toolkit';
const localStorageMiddleware = ({ getState }) => {
return (next) => (action) => {
const result = next(action);
localStorage.setItem('userState', JSON.stringify(getState().user));
return result;
};
};
const reHydrateStore = () => {
if (localStorage.getItem('userState') !== null) {
return { user: JSON.parse(localStorage.getItem('userState')) };
}
};
export default configureStore({
reducer: {
page: pageReducer,
modal: modalReducer,
user: userReducer
},
preloadedState: reHydrateStore(),
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({
serializableCheck: false
}).concat(localStorageMiddleware)
});
Step 3
create wrapping index.js root file
import 'core-js/stable';
import 'regenerator-runtime/runtime';
import React from 'react';
import ReactDOM from 'react-dom';
import '../node_modules/bootstrap/dist/css/bootstrap.min.css';
import './styles/main.scss';
import App from './App';
import store from './redux/store';
import { Provider } from 'react-redux';
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
Step 4
create AuthRequired root file
import { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Navigate } from 'react-router';
import { logout } from '../redux/reducer/user';
export default function AuthRequired({ children }) {
let [redirect, setRedirect] = useState(false);
let dispatch = useDispatch();
let user = useSelector((state) => state.user);
useEffect(() => {
if (!user.isAuthenticated) {
dispatch(logout());
setRedirect(true);
}
}, [user]);
return redirect ? <Navigate to="/login" /> : children;
}
Step 4
create login file
import { useNavigate } from 'react-router';
import Button from '../../components/button';
import Input from '../../components/input';
import './index.scss';
import Logo from '../../assets/LUMOS-logo.svg';
import { useState } from 'react';
import authControllers from '../../api/auth';
import { useDispatch } from 'react-redux';
import { login } from '../../redux/reducer/user';
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
export default function Login() {
let dispatch = useDispatch();
const [state, setState] = useState({
email: '',
password: ''
});
const [passwordShown, setPasswordShown] = useState(false);
const clickhandler = () => {
setPasswordShown(!passwordShown);
};
const [loading, setLoading] = useState(false);
const [err, setErr] = useState('');
const navigate = useNavigate();
function handleSubmit(e) {
setLoading(true);
setErr('');
e.preventDefault();
let { email, password } = state;
let body = {
email,
password
};
authControllers
.login(body)
.then((res) => {
setLoading(false);
let response = res.data.response.message;
dispatch(login({ ...response, isAuthenticated: true }));
navigate(`/home`);
})
.catch((err) => {
setLoading(false);
let errMessage =
(err.response &&
err.response.data &&
err.response.data.response &&
err.response.data.response.message) ||
'Network Error';
setErr(errMessage);
});
}
function handleChange(e) {
let { value, id } = e.target;
setState({
...state,
[id]: value
});
}
return (
<div className="login-page">
<form onSubmit={handleSubmit}>
<div className="d-flex flex-column">
<img className="login-page__logo" src={Logo} alt="logo" />
<Input
onChange={handleChange}
type="email"
placeholder="Email"
className="mb-4"
login
id="email"
value={state.email}
/>
<Input
onChange={handleChange}
type={passwordShown ? 'text' : 'password'}
placeholder="Password"
className="mb-4"
id="password"
login
value={state.password}
/>
<span className="passIcon" onClick={clickhandler}>
{passwordShown ? (
<FontAwesomeIcon color={`#fff`} icon={faEye} />
) : (
<FontAwesomeIcon color={`#9496A2`} icon={faEyeSlash} />
)}
</span>
<Button loading={loading} width="480px" primary type="submit">
Log In
</Button>
{err && <p className="text-danger text-center mt-4">{err}</p>}
</div>
</form>
</div>
);
}
Code is very useful
ReplyDelete