Front-End Architecture

Introduction

Mataara uses the ReactJS framework to provide a front-end user interface, built on top of Django REST Framework APIs. The React frontend also uses Redux to store the state of the app in a single state tree.

What does Redux do, and how does it work?

Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments (client, server, and native), and are easy to test.

Redux only has a single store that holds no logic by itself. Actions are dispatched and handled directly by the store, eliminating the need for a standalone dispatcher. In turn, the store passes the actions to state-changing functions called reducers. API or client-side middleware may also be included to add authentication, or to stop, modify or add more actions.

Redux Components

Redux features four major system components:

Store:
Controls the state.
Actions:
Describe the changes we want to make.
Reducers:
Services that state change based on the requested action.
Middleware:
Handles housekeeping tasks of the app.

N.B.: Reducers never change their state; they are immutable. An entire application state is kept in a single location, the store- This provides enormous benefits during debugging, serialization and development.

Redux Principles

Redux has three major principles to be aware of:

State Principle:
The state of an application is stored in an object tree within a single store, meaning everything that changes in an app is contained in a single object called state or state tree.
Action Principle:
A state tree cannot be modified or written to. To change a state, an action has to be dispatched. An action ensures that views nor the network callbacks will ever write directly to the state. Actions must be plain JS objects, that can be logged, serialized, stored and later replayed for debugging or testing purposes.
Reducer Principle:
Reducers exists to specify how the state tree is transformed by actions. Reducers are pure functions that takes the previous state and an action then return the next state. Using the default switch, it must return current state for undefined actions.

Further description can be found here: https://redux.js.org/introduction/three-principles

Basic Requirements

  • NodeJS 5.0.0 or higher, plus npm
  • React + Redux
  • Babel 6
  • Webpack
  • ESLint
  • Redux DevTools + Logger middleware (easily removable/replaceable if you need something else)
  • Jest to run unit tests

Directory / File Structure

├── devServer.js
├── README.md
├── webpack-stats.json
├── src
│   ├── index.js
│   ├── actions
│   ├── store
│   ├── components
│   ├── constants
│   ├── containers
│   ├── api.js
│   └── reducers
├── setupJest.js
├── webpack.config.prod.js
├── index_frontend.html
├── package.json
└── webpack.config.dev.js

Actions Directory

Actions are payloads of information that send data from the application to the store. They are the only source of information for the store. We put all our action files in this directory.

Constants Directory

All types of action that are performed within the app are defined in the ActionsTypes.js file. The date.js file contains a standard date formatting string.

Reducers Directory

Actions describe events that have happened, but don’t specify how the application’s state changes in response. This is the job of reducers. Because we are using Redux, we combine reducers using the Redux tool combineReducers.

Containers Directory

Container components are a React pattern used to separate data fetching from rendering concerns. The idea is simple: A container does data fetching, and then renders that data using its corresponding sub-component.

Store Directory

The Store is the object that brings actions and reducers together. We only have a single store in our Redux application. The store has the following responsibilities:

  • Holds the application state
  • Allows access to that state via getState()
  • Allows it to be updated via dispatch(action)
  • Registers listeners via subscribe(listener)
  • Handles unregistering of listeners via the function returned by subscribe(listener)

api.js File

This file is responsible for building the query strings, fetching data from Django REST API and parsing the JSON responses. Every action uses API file functions to fetch data.

Components Directory

Components in ReactJS are like LEGO pieces. Every part of the application’s visuals should be wrapped inside a self-contained component module. Our components use Material UI, a set of React components that implement Google’s Material design.

Unit Test Directory

We use Jest to create unit tests. Jest test files are placed into a subdirectory called __tests__. It will look automatically for test files inside that subdirectory.

ESLint

We use the ESLint JavaScript linting utility to find problematic patterns or code that don’t adhere to certain style guidelines. Linting rules are defined in a .eslintrc file.

You can find more ESLint rules here.