Currently, I’m working with NextJS 14 and Redux Toolkit so I need suggestions on Routing and Navigation on Api success calls so need some guidance with that, I tried some methods but I’m pretty sure it’s not a standard approach, so I need proper guidance on api call success routing, I tried some code and Thanks In Advance.
import axiosInstance from '@/utils/axios';
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
export const loginUser = createAsyncThunk(
'/user/loginUser',
async (userData, dispatch) => {
console.log(userData);
try {
const response = await axiosInstance.post(`/app_login`, userData);
console.log(response.request);
if (response.data.success) {
console.log(response.data.data, "Api response");
return response.data.data
} else {
return rejectWithValue(error.response.message)
}
} catch (error) {
console.log(error);
const errorMessage = error.response.data.message || 'An error occurred';
dispatch(removeUser(errorMessage));
console.error('Login failed:', error);
return rejectWithValue(error.response.message)
}
}
)
export const signupUser = createAsyncThunk(
'/user/signupUser',
async (data, { rejectWithValue }) => {
try {
const response = await axiosInstance.post('/app_register', data)
return response.data.data.user
} catch (error) {
return rejectWithValue(error.response.data.message)
}
}
)
const userSlice = createSlice({
name: 'user',
initialState: {
user: {},
errorMsg: '',
isLoading: false,
success: false
},
reducers: {
setUser: (state, action) => {
state.user = action.payload;
state.errorMsg = ''
},
removeUser: (state, action) => {
state.user = null
state.errorMsg = action.payload
}
},
extraReducers: (builder) => {
builder
.addCase(loginUser.pending, (state, action) => {
state.isLoading = true;
state.success = false;
})
.addCase(loginUser.fulfilled, (state, action) => {
debugger
state.user = action.payload;
state.success = true;
state.isLoading = false;
state.errorMsg = null;
})
.addCase(loginUser.rejected, (state, action) => {
console.log(action.payload);
debugger
state.errorMsg = action.payload || 'An error occurred during login.';
state.user = null
state.isLoading = false;
state.success = false;
})
.addCase(signupUser.pending, (state, action) => {
state.isLoading = true;
})
.addCase(signupUser.fulfilled, (state, action) => {
debugger
state.user = action.payload;
state.errorMsg = null;
})
.addCase(signupUser.rejected, (state, action) => {
debugger
state.errorMsg = action.payload || 'An error occurred during signup.';
state.user = null
});
}
});
export const { setUser, removeUser } = userSlice.actions;
export default userSlice.reducer;
Here is my Login screen code
"use client";
import Link from 'next/link';
import React, { useEffect, useState } from 'react';
import { useRouter } from 'next/router'; // Correct import for useRouter if you're using Next.js
import { useDispatch, useSelector } from 'react-redux';
import { loginUser } from './redux/slice/authSlice'; // Assuming loginUser is the correct function from your authSlice
import Loader from '@/utils/loader'; // Ensure the path is correct based on your directory structure
export default function Index() {
const msg = useSelector(state => state.user.errorMsg);
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const dispatch = useDispatch();
const router = useRouter();
const isLoading = useSelector(state => state.user.isLoading);
useEffect(() => {
// Assuming you are getting some data from localStorage or similar
const data = localStorage.getItem('userData');
if (data) {
const parsedData = JSON.parse(data);
setEmail(parsedData.email || '');
setPassword(parsedData.password || '');
}
}, []);
const handleLogin = (e) => {
e.preventDefault();
dispatch(loginUser({ email, password })).then((action) => {
if (action.meta.requestStatus === 'fulfilled') {
console.log('Login successful:', action.payload);
router.push('/dashboard');
}
}).catch((err) => {
console.log('Error during login:', err);
});
};
return (
<div className='h-screen flex justify-center items-center'>
<div className='w-full sm:max-w-[606px] px-4 sm:px-0 m-auto py-5 sm:py-10'>
<Link href="/"><img className='m-auto w-36 sm:w-48' src="/images/demo.png" alt="Demo logo" /></Link>
<div className='text-center pt-5 sm:pt-10'>
<h2 className='text-white text-xl sm:text-2xl md:text-3xl font-bold'>Login</h2>
<h3 className='text-white sm:text-lg pt-1 sm:pt-2 md:pt-3'>Login to your Demo account</h3>
<div className='pt-5 sm:pt-7 flex flex-col gap-3'>
<label className='text-dark-400 text-start sm:text-lg block'>Username, Email or Cell Phone</label>
<input className='w-full py-3 sm:py-4 sm:text-lg text-white placeholder:text-white bg-gray border-none rounded-md pl-12 sm:pl-16'
value={email} onChange={(e) => setEmail(e.target.value)} type="text" placeholder='[email protected]' />
</div>
<div className='pt-5 sm:pt-7 flex flex-col gap-3'>
<label className='text-dark-400 text-start sm:text-lg block'>Password</label>
<input className='w-full py-3 sm:py-4 sm:text-lg text-white placeholder:text-white bg-gray border-none rounded-md pl-12 sm:pl-16'
type="password" value={password} onChange={(e) => setPassword(e.target.value)} placeholder='* * * * * *' />
</div>
{msg && <p className='text-red'>{msg}</p>}
<button onClick={handleLogin} className="p-3 sm:p-[14px] sm:text-lg mt-4 sm:mt-8 inline-block rounded-xl bg-gradient-to-r from-primary to-secondary text-white overflow-hidden font-semibold sm:min-w-[378px]">
{isLoading ? <Loader /> : 'Login'}
</button>
</div>
</div>
</div>
);
}