Till now I was redirecting to the User Dashboard from the React component, but I want to apply a different approach, I want to redirect after getting the success response from the saga itself.
For this, I have attempted to use redux-first-history
(which comes with the support of react-router6) I have followed their documentation, almost everything is working but an action @@router/CALL_HISTORY_METHOD
getting called twice.
Here are my routes
export default function App() {
return (
<AuthProvider>
<Router history={history}>
<Routes>
<Route element={<Layout />}>
<Route path="/" element={<PublicPage />} />
<Route path="/login" element={<LoginPage />} />
<Route
path="/protected"
element={
<RequireAuth>
<ProtectedPage />
</RequireAuth>
}
/>
</Route>
</Routes>
</Router>
</AuthProvider>
);
}
which goes across the project, below is my store.
import { applyMiddleware, compose, createStore } from "redux";
import { persistReducer, persistStore } from "redux-persist";
import storage from "redux-persist/lib/storage";
import createSagaMiddleware from "redux-saga";
import rootReducer from "../store/reducers";
import { watchAuth } from "../store/sagas/index";
import { createReduxHistoryContext } from "redux-first-history";
import { createBrowserHistory } from "history";
const composeEnhancers =
process.env.NODE_ENV === "development"
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
: null || compose;
const { createReduxHistory, routerMiddleware } = createReduxHistoryContext({
history: createBrowserHistory(),
oldLocationChangePayload: true,
showHistoryAction: true,
});
const sagaMiddleware = createSagaMiddleware();
const middleware = [sagaMiddleware, routerMiddleware];
const persistConfig = {
key: "root",
storage,
whitelist: ["auth"],
};
const persistedReducer = persistReducer(persistConfig, rootReducer);
export const store = createStore(
persistedReducer,
composeEnhancers(applyMiddleware(...middleware)),
);
const persistor = persistStore(store);
sagaMiddleware.run(watchAuth);
export const history = createReduxHistory(store);
export default store;
export { persistor };
and my Saga
import { call, delay, put } from "redux-saga/effects";
import axios from "../../../config/axios";
import {
authFail,
authStart,
authSuccess,
checkAuthTimeout,
logout,
logoutSucceed,
setAlert,
} from "../../actions/auth/auth";
import { LOGIN_API } from "../../apiCollecitions";
import { push } from "redux-first-history";
export function* authLoginSaga(action) {
yield put(authStart());
const authData = {
email: action.email,
password: action.password,
};
try {
const response = yield axios.post(
`${LOGIN_API}?lng=${localStorage.getItem("i18nextLng")}&active=true`,
authData,
);
yield localStorage.setItem("token", response.data.token);
yield localStorage.setItem("expirationDate", expirationDate);
yield put(authSuccess(response.data.token));
yield put(push("/protected")); //should redirect to the specified route
} catch (error) {
yield put(authFail(error.response.data.message));
}
}
I have also set up a sample GitHub repo for the same, for your reference.