Login – ReduxToolkit Example – 1
1.userActionTypes.js
export const USER_FETCH_REQUESTED = "USER_FETCH_REQUESTED";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAIL = "LOGIN_FAIL";
// Define other action types as needed
2.userActions.js
import {
USER_FETCH_REQUESTED,
LOGIN_SUCCESS,
LOGIN_FAIL,
// Import other action types as needed
} from "./userActionTypes";
export const userFetchRequestedAction = (payload) => ({
type: USER_FETCH_REQUESTED,
payload,
});
export const loginSuccessAction = (result) => ({
type: LOGIN_SUCCESS,
payload: result,
});
export const loginFailAction = (error) => ({
type: LOGIN_FAIL,
payload: error,
});
// Define other action creators as needed
3.APIs
import apiClient from 'services/axios'
const BASE_URL = '/api/auth'
export async function load(payload) {
return apiClient
.get(`${BASE_URL}`, payload)
.then(response => ({ response }))
.catch(error => ({ error }))
}
export async function loginApi(payload) {
console.trace("loginapi")
return apiClient
.post(`${BASE_URL}/signin`, payload)
.then(response => ({ response }))
.catch(error => ({ error }))
}
export async function logout() {
return apiClient
.delete(`${BASE_URL}/logout`)
.then(response => ({ response }))
.catch(error => ({ error }))
}
3.sagas.js
// sagas/dataSaga.js
import { takeLatest, call, put } from 'redux-saga/effects';
import {loginApi, load, logout} from '../../api/user'
import { loginFailAction, loginRequestAction, loginSuccessAction } from './userslices'; // Import your actions
// Worker Saga: Handles the data fetching operation
function* userFetchSaga(action) {
try {
//const response = yield call(axios.get, 'https://api.example.com/data');
yield put(loginRequestAction());
const response = yield call(loginApi, action.payload);
const user = response.response.data;
yield put(loginSuccessAction(user));
} catch (error) {
yield put(loginFailAction(error.message)); // Dispatch an error action if fetching fails
}
}
// Watcher Saga: Listens for the FETCH_DATA action
export function* User() {
yield takeLatest('USER_FETCH_REQUESTED', userFetchSaga);
}
4.userslices.js
import { createSlice } from "@reduxjs/toolkit";
import store from 'store'
const STORED_USER = (storedUser) => {
const user = {};
Object.keys(storedUser).forEach((key) => {
const item = store.get(`user.${key}`);
user[key] = typeof item !== "undefined" ? item : storedUser[key];
});
return user;
};
export const userStateData = {
loading: false,
accessToken: null,
data: null,
staff: null,
business: null,
location: null,
canRegister: false,
loggingIn: false,
email: null,
displayChangeEmailModal: false,
isAuthenticated: false,
username:null,
email:null,
userid: null,
errors: {
register: null,
change: null,
login: null,
recover: null,
reset: null,
business: null,
},
};
const userSlice = createSlice({
name: "user",
initialState: {
...STORED_USER(userStateData),
},
reducers: {
loginRequestAction(state, action) {
console.trace("loginRequestAction")
return {
...state,
loading: true,
};
},
loginSuccessAction(state, action) {
return {
loading: false,
isAuthenticated: true,
userid: action.payload.id,
username:action.payload.username,
email:action.payload.email,
accessToken:action.payload.accessToken
};
},
loginFailAction(state, action) {
return {
...state,
loading: false,
error: action.payload,
};
},
clearErrorAction(state, action) {
return {
...state,
error: null,
};
},
},
});
const { actions, reducer } = userSlice;
export const { loginRequestAction, loginSuccessAction, loginFailAction, clearErrorAction } = actions;
export default reducer;
5.login
import { Fragment, useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { userFetchRequestedAction } from "../../../redux/user/userActions";
import {} from '../../../redux/user/userslices'
export default function Login() {
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const dispatch = useDispatch();
const navigate = useNavigate();
const location = useLocation();
const { loading, error, isAuthenticated } = useSelector(
(state) => state.user
);
const submitHandler = (e) => {
e.preventDefault();
//dispatch(userFetchSaga({username, password}));
// Dispatch the 'USER_FETCH_REQUESTED' action with username and password
dispatch(userFetchRequestedAction({ username, password }));
};
useEffect(() => {
if (isAuthenticated) {
navigate("/dashboard");
}
if (error) {
console.log("Login Error : ", error);
return;
}
}, [error, isAuthenticated, dispatch, navigate]);
return (
<Fragment>
<div >
<div >
<form onSubmit={submitHandler} >
<h1 >Login</h1>
<div >
<label >username</label>
<input
type="username"
id="username_field"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
<div >
<label >Password</label>
<input
type="password"
id="password_field"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
</div>
<button
id="login_button"
type="submit"
>
LOGIN
</button>
</form>
</div>
</div>
</Fragment>
);
}
//disabled={loading}
ToDoList – ReduxToolkit Example – 2
1.App.js
import React from "react";
import "./styles.css";
import { Provider } from "react-redux";
import ListTodo from "./ListTodo";
import store from "./store";
console.log(store.getState());
export default function App() {
return (
<Provider store={store}>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<ListTodo />
</div>
</Provider>
);
}
2.index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
3. store.js
import {
createSlice,
configureStore,
getDefaultMiddleware
} from "@reduxjs/toolkit";
import createSagaMiddleware from "redux-saga";
import saga from "./saga";
const todoSlice = createSlice({
name: "todo",
initialState: {
todos: []
},
reducers: {
fetchData: (state, action) => {
return {
todos: action.payload
};
}
}
});
export const { fetchData } = todoSlice.actions;
let sagaMiddleware = createSagaMiddleware();
const middleware = [...getDefaultMiddleware({ thunk: false }), sagaMiddleware];
const store = configureStore({
reducer: {
todo: todoSlice.reducer
},
middleware
});
sagaMiddleware.run(saga);
export default store;
4.sagaActions.js
export const sagaActions = {
FETCH_DATA_SAGA: "FETCH_DATA_SAGA"
};
5.saga.js
import { call, takeEvery, put } from "redux-saga/effects";
import Axios from "axios";
import { fetchData } from "./store";
import { sagaActions } from "./sagaActions";
let callAPI = async ({ url, method, data }) => {
return await Axios({
url,
method,
data
});
};
export function* fetchDataSaga() {
try {
let result = yield call(() =>
callAPI({ url: "https://5ce2c23be3ced20014d35e3d.mockapi.io/api/todos" })
);
yield put(fetchData(result.data));
} catch (e) {
yield put({ type: "TODO_FETCH_FAILED" });
}
}
export default function* rootSaga() {
yield takeEvery(sagaActions.FETCH_DATA_SAGA, fetchDataSaga);
}
6.ListTodo.js
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { sagaActions } from "./sagaActions";
export default function() {
const dispatch = useDispatch();
const todos = useSelector(state => state.todo.todos);
console.log(todos);
const renderList = () => {
return todos.map(todo => {
return <p key={todo.id}>{todo.title}</p>;
});
};
return (
<div>
<button onClick={() => dispatch({ type: sagaActions.FETCH_DATA_SAGA })}>
Getdata
</button>
{renderList()}
</div>
);
}