I am building a Jhipster React generated project. My problem is I couldn't manage to chain reducer functions.
Simply, I want to chain getSession()
function with another function in the authentication reducer.
In my component I want to handle then()
operation like getSession().then(....
Can you please help for this?
Here is the authentication.ts
reducer:
authentication.ts
import axios from 'axios';
import { Storage } from 'react-jhipster';
import { REQUEST, SUCCESS, FAILURE } from 'app/shared/reducers/action-type.util';
export const ACTION_TYPES = {
LOGIN: 'authentication/LOGIN',
GET_SESSION: 'authentication/GET_SESSION',
LOGOUT: 'authentication/LOGOUT',
CLEAR_AUTH: 'authentication/CLEAR_AUTH',
ERROR_MESSAGE: 'authentication/ERROR_MESSAGE'
};
const AUTH_TOKEN_KEY = 'jhi-authenticationToken';
const initialState = {
loading: false,
isAuthenticated: false,
loginSuccess: false,
loginError: false, // Errors returned from server side
showModalLogin: false,
account: {} as any,
errorMessage: null as string, // Errors returned from server side
redirectMessage: null as string
};
export type AuthenticationState = Readonly<typeof initialState>;
// Reducer
export default ( state: AuthenticationState = initialState, action ): AuthenticationState => {
switch ( action.type ) {
case REQUEST( ACTION_TYPES.LOGIN ):
case REQUEST( ACTION_TYPES.GET_SESSION ):
return {
...state,
loading: true
};
case FAILURE( ACTION_TYPES.LOGIN ):
return {
...initialState,
errorMessage: action.payload,
showModalLogin: true,
loginError: true
};
case FAILURE( ACTION_TYPES.GET_SESSION ):
return {
...state,
loading: false,
isAuthenticated: false,
showModalLogin: true,
errorMessage: action.payload
};
case SUCCESS( ACTION_TYPES.LOGIN ):
return {
...state,
loading: false,
loginError: false,
showModalLogin: false,
loginSuccess: true
};
case ACTION_TYPES.LOGOUT:
return {
...initialState,
showModalLogin: true
};
case SUCCESS( ACTION_TYPES.GET_SESSION ): {
const isAuthenticated = action.payload && action.payload.data && action.payload.data.activated;
return {
...state,
isAuthenticated,
loading: false,
account: action.payload.data
};
}
case ACTION_TYPES.ERROR_MESSAGE:
return {
...initialState,
showModalLogin: true,
redirectMessage: action.message
};
case ACTION_TYPES.CLEAR_AUTH:
return {
...state,
loading: false,
showModalLogin: true,
isAuthenticated: false
};
default:
return state;
}
};
export const displayAuthError = message => ( { type: ACTION_TYPES.ERROR_MESSAGE, message } );
export const getSession = () => dispatch => {
dispatch( {
type: ACTION_TYPES.GET_SESSION,
payload: axios.get( '/api/account' )
} );
};
export const login = ( username, password, rememberMe = false ) => async ( dispatch, getState ) => {
const result = await dispatch( {
type: ACTION_TYPES.LOGIN,
payload: axios.post( '/api/authenticate', { username, password, rememberMe } )
} );
const bearerToken = result.value.headers.authorization;
if ( bearerToken && bearerToken.slice( 0, 7 ) === 'Bearer ' ) {
const jwt = bearerToken.slice( 7, bearerToken.length );
if ( rememberMe ) {
Storage.local.set( AUTH_TOKEN_KEY, jwt );
} else {
Storage.session.set( AUTH_TOKEN_KEY, jwt );
}
}
dispatch( getSession() );
};
export const clearAuthToken = () => {
if ( Storage.local.get( AUTH_TOKEN_KEY ) ) {
Storage.local.remove( AUTH_TOKEN_KEY );
}
if ( Storage.session.get( AUTH_TOKEN_KEY ) ) {
Storage.session.remove( AUTH_TOKEN_KEY );
}
};
export const logout = () => dispatch => {
clearAuthToken();
dispatch( {
type: ACTION_TYPES.LOGOUT
} );
};
export const clearAuthentication = messageKey => ( dispatch, getState ) => {
clearAuthToken();
dispatch( displayAuthError( messageKey ) );
dispatch( {
type: ACTION_TYPES.CLEAR_AUTH
} );
};
store.ts
import { createStore, applyMiddleware, compose } from 'redux';
import promiseMiddleware from 'redux-promise-middleware';
import thunkMiddleware from 'redux-thunk';
import reducer, { IRootState } from 'app/shared/reducers';
import DevTools from './devtools';
import errorMiddleware from './error-middleware';
import notificationMiddleware from './notification-middleware';
import loggerMiddleware from './logger-middleware';
import { loadingBarMiddleware } from 'react-redux-loading-bar';
const defaultMiddlewares = [
thunkMiddleware,
errorMiddleware,
notificationMiddleware,
promiseMiddleware(),
loadingBarMiddleware(),
loggerMiddleware
];
const composedMiddlewares = middlewares =>
process.env.NODE_ENV === 'development'
? compose(
applyMiddleware(...defaultMiddlewares, ...middlewares),
DevTools.instrument()
)
: compose(applyMiddleware(...defaultMiddlewares, ...middlewares));
const initialize = (initialState?: IRootState, middlewares = []) => createStore(reducer, initialState, composedMiddlewares(middlewares));
export default initialize;
Home Component
import './home.css';
import React from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { Button, Row, Col, Alert, Table } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IRootState } from 'app/shared/reducers';
import { getSession } from 'app/shared/reducers/authentication';
import { getWhoIsInsideInfo, exitVisitor } from 'app/entities/visitor/visitor.reducer';
import { IVisitorInsideInfo } from 'app/shared/model/visitors_inside.model';
import { TextFormat } from 'react-jhipster';
import { APP_TIMESTAMP_FORMAT } from 'app/config/constants';
import VisitorDeleteDialog from 'app/entities/visitor/visitor-delete-dialog';
export interface IHomeProp extends StateProps, DispatchProps { }
const mapStateToProps = ( { authentication, visitorsInsideInfo }: IRootState ) => ( {
account: authentication.account,
isAuthenticated: authentication.isAuthenticated,
visitorInsideList: visitorsInsideInfo.insiderEntities,
loginSuccess: authentication.loginSuccess
} );
type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = typeof mapDispatchToProps;
const mapDispatchToProps = { getSession, getWhoIsInsideInfo, exitVisitor };
export class Home extends React.Component<IHomeProp> {
interval: any;
orgDispatch: any;
constructor( props ) {
super( props );
this.renderVisitorsInside = this.renderVisitorsInside.bind( this );
}
setListTimer() {
console.log( 'DIS' );
}
getList = () => {
if ( this.props.account && this.props.account.login ) {
getWhoIsInsideInfo();
}
};
.....
}
In my Home component I want to first call getSession then call getList. If response was OK else reject it. Thanks from now on.
It looks like you have everything right. You just need to call your reducer functions with
dispatch
.For example: