Generating source code

Let's take a look at the generated code. Since we already saw the server-side code in previous chapters, we will only look at the client-side code here:

The structure is quite similar to what we saw for Angular, but the React code is organized slightly differently. We are concerned only about the code inside src/main/webapp/app as everything else is exactly the same as what we saw for the Angular application.

Let's take a look at some of the important parts of the code:

...
const devTools = process.env.NODE_ENV === 'development' ? <DevTools /> : null;
const store = initStore();
registerLocales(store);

const actions = bindActionCreators({ clearAuthentication }, store.dispatch);
setupAxiosInterceptors(
() => actions.clearAuthentication('login.error.unauthorized')
);

const rootEl = document.getElementById('root');
const render = Component =>
ReactDOM.render(
<AppContainer>
<Provider store={store}>
<div>
...
{devTools}
<Component />
</div>
</Provider>
</AppContainer>,
rootEl
);

render(AppComponent);
...
...
export class App extends React.Component<IAppProps> {
componentDidMount() {
this.props.getSession();
}

handleLogout = () => {
this.props.logout();
};

render() {
const paddingTop = '60px';
return (
<Router>
<div className="app-container" style={{ paddingTop }}>
<Header
...
/>
<div className="container-fluid view-container" id="app-view-container">
<Card className="jh-card">
<AppRoutes />
</Card>
<Footer />
</div>
<ModalContainer />
</div>
</Router>
);
}
}
...

The order of the middlewares in the array is important as they act like a pipeline, passing actions from one middleware to another as shown here:

const defaultMiddlewares = [
thunkMiddleware,
errorMiddleware,
notificationMiddleware,
promiseMiddleware(),
loadingBarMiddleware(),
loggerMiddleware
];
...

export const ACTION_TYPES = {
LOGIN: 'authentication/LOGIN',
...
};

const initialState = {
...
};

// Reducer
export default (state = initialState, action) => {
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 SUCCESS(ACTION_TYPES.LOGIN):
return {
...state,
loading: false,
loginError: false,
showModalLogin: false,
loginSuccess: true
};
...
default:
return state;
}
};
...
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('jhi-authenticationToken', jwt);
} else {
Storage.session.set('jhi-authenticationToken', jwt);
}
}
dispatch(getSession());
};
...

The folder structure of the unit test code is also quite similar: