How to use redux toolkit in react js




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>
    );
}


Comments

Post a Comment