cra-template-idrica-app v0.1.3
This project was bootstrapped with Create React App and has some extra libraries and file structure that we consider good to start a React project.
Original Create React App README available here
File organization
src
├─── assets
├─── components
| ├─── Dropdown
| ├─── Switcher
│ └─── TextField
├─── containers
| ├─── Layout
| | ├─── components/Footer
| │ └─── components/Header
│ └─── WithSettings
├─── pages
| ├─── Home
│ └─── Login
├─── redux
├─── routes
├─── services
├─── styles
├─── translations
└─── utils
- assets: All static files we need to run the project such as images, icons or SVGs.
- components: Here we place all the atomic React components. This means, reusable and indivisible React components used anywhere in the application. Such as buttons, inputs, dropdowns, etc.
- containers: Here we place the common containers used in various places of the application. In this template, this module is formed by the Layout (the header and footer) and one HOC (WithSettings).
- pages: Here we place all the pages of the application.
- redux: This is where we place the Redux store config and a "global" reducer is placed here (this wll be explained further). We use
redux
andredux-thunk
as a middleware. - routes: React routing config is placed here.
- services: This module contains the GLOBAL the API calls we make in the application.
- styles: All the common and main SASS files are here.
- translations: Internationalization.
- utils: the GLOBAL functions or constants that can be useful for the application are placed here.
We recommend that the application should structure files using a "feature folder" approach (all files for a feature in the same folder). That is to say, we will have in the same folder, the styles, the services, the redux logic, the utils folder with some configuration or usefull functions, etc. If some logic is repeated we should keep our code DRY (Don’t Repeat Yourself) by exporting repeated logic to a singular location (global folders) and importing it where used.
In this template, we wanted to leave the project as clean as possible, and we can't show (with a real case) the advantages of this file structure. However, we came to the conclusion that it is a good way to keep the code readable and scalable. And the HomePage component has the folders created with dummy files inside to reflect how it would look.
Local development
Requirements
- node 12.xx.x
- npm 6.x.x
About internationalization
We are using react-intl for internationalization. Follow the next steps to include translations in the application.
- Create a
messages.js
file inside the same folder where the React component is. Import defineMessages from
react-intl
and define the translations only in the default language. For example:import { defineMessages } from "react-intl"; export default defineMessages({ LoginButton: { id: "app.Layout.Header.LoginButton", defaultMessage: "Login", }, LogoutButton: { id: "app.Layout.Header.LogoutButton", defaultMessage: "Logout", }, });
Run the following command in the console:
npm run extract-messages
- This will generate (or update) files inside
src/translations
likeen.json
andes.json
. You can modify the script to generate the translation in many languages as you want. If you look into the default language json file (en.json
), you will see something like this:{ "app.Layout.Header.LoginButton": "Login", "app.Layout.Header.LogoutButton": "Logout" }
If you look at the other language json file (
es.json
), you will see something like this:{ "app.Layout.Header.LoginButton": "", "app.Layout.Header.LogoutButton": "" }
You only need to fill the translations.
And finally, in order to use these translations inside a React component, you need to use the
useIntl
hook. For example:import { useIntl } from "react-intl"; const LoginButton = () => { const intl = useIntl(); return ( <button> {intl.formatMessage({ id: "app.Layout.Header.LoginButton", })} </button> ); }; export default LoginButton;
About testing
To perform the tests, Jest
is used as a testing framework and the React Testing Library
provides us with a series of utilities that allow us to test the components of React.
Redux configuration
The template provides basic Redux configuration with feature based folder structure. We recommend that the application uses the "ducks" pattern (all Redux logic for a feature in a single file), rather than splitting logic across separate folders by "type" of code. For this reason, we can have multiple redux folders along the application. For example, we have have a redux folder inside de LoginPage component, where we define the actions, reducers, etc, which are related to the login page. And then we combine the reducers in the main reducer.
In addtion, we use immer in the reducers to handle the inmutability. For example:
import produce from "immer"
const loginPageReducer = (state = initialState, action) =>
produce(state, draft => {
switch (action.type) {
case SET_LOGIN_PENDING:
draft.isLoginPending = action.isLoginPending;
break;
case SET_LOGIN_SUCCESS:
draft.isLoginPending = false;
draft.userName = action.username;
break;
case SET_LOGIN_ERROR:
draft.isLoginError = action.loginError;
break;
default:
return draft;
}
});
Also you can use Redux devtools browser extension to debug your redux state in the console.
Eslint configurations
The template extends CRA ESLint rules with a custom set, tailored for the reasonable and clean development process. Eslint rules are commented for your convenience feel free to tweak or remove them inside .eslintrc
. No judgment.
Prettier
We added prettier
to force consistent formatting. If you don't like some rule you can use tweak prettier rules inside .prettierrc
file to match your code style.
Husky
We added husky
to force use the git hooks to prevent push "bad" commit to the repository. Currently, husky is set to run before the push
command, and it checks if the linter and the tests pass.
Styling
We use saas files for styling. For the common and main SASS we use a mix of SMACSS + ITCSS + BEM architecture. They are placed in the styles folder.
- base: For defaults (html, body, etc) and resets.
- settings: Here we place the variables. Font, colors definitions, etc.
- temp: Temporary styles when you don't know where to include it, and you will reorganize it later.
- themes: Color schemes, typography, etc.
- utils: Mixins and functions.
- app-styles.scss: The main file. The other files, related to the styles, are imported here.
- style-utils.scss: This file is to import inside any Component or Module .scss if you need it.
Available scripts
In the project directory, you can run (among others):
start
- runs the app in the development mode. Open http://localhost:3000 to view it in the browser.test
- launches the test runner in the interactive watch mode.build
- builds the app for production to thebuild
folder.eject
- exposes content ofreact-script
package.extract-messages
- generates the translation files.lint
- lints project files according to eslint rules, see below. Typical use case: continuous integration environments, Travis, CircleCI, etc.lint:fix
- same aslint
, but also fixes errors, when possible. Typical use case: local development environment, git hooks.prettier:check
- shows formatting errors.prettify
- fixes formatting errors, when possible.run-all-tests
- runs the linter and the tests in parallel.publish-template
- publishes the template in npm, before it, some files are copied from the project to the template folder to keep updated it.