0.1.3 • Published 4 years ago

cra-template-idrica-app v0.1.3

Weekly downloads
15
License
-
Repository
-
Last release
4 years ago

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 and redux-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.

Screenshot

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.

  1. Create a messages.js file inside the same folder where the React component is.
  2. 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",
        },
    });
  3. Run the following command in the console:

    npm run extract-messages
  4. This will generate (or update) files inside src/translations like en.json and es.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"
    }
  5. 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.

  6. 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.

Screenshot

  • 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 the build folder.

  • eject - exposes content of react-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 as lint, 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.