Redux Toolkit Basic

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

Leave a Reply

Your email address will not be published. Required fields are marked *