Engineering the Web

We at Modern Democracy are focused on delivering the best user experiences to our customers, fast – to do that we need to rethink common engineering practices and leverage cutting edge technologies.  We use React as the JavaScript framework for our web application. The reason we choose React is simple, everyone else is using it so we decided we may as well jump on the band wagon too. This statement of course is not entirely true, but I am sure with all the hype around React a statement like that wouldn’t be hard to believe. I don’t think any passionate Front End or Full Stack Developer would say they haven’t played about with React at some point or at least read about it.

We did of course choose React for several reasons, evaluating how it would meet our needs:

  1. Well documented and supported.

  2. Good established and proven patterns focusing on reusable components.

  3. Unopinionated framework which allows us to be more flexible in your approaches to implementing solutions to various problems.

  4. The Virtual DOM allows what we produce to be fast and responsive

  5. Excellent developer tools for React and Redux.

  6. Redux allows us to implement the Flux pattern easily keeping our state manageable as our platform grows (I will expand on this point later).

I could continue on with this list, but you get the idea. I think the main benefit we have found from actually using React is that it allows us to develop in a truly agile way.

What I mean by this is we are able to produce features quickly and to a very high standard within a 2-week sprint, get feedback from the business on the resulting features and act or refine accordingly.  Having a properly quick feedback development loop means we are able to meet requirements even if they change (Which we all know too often do). Of course, the framework doesn’t magically give us the ability to work in such an agile way, it is how we use the framework and the patterns in particular we use that help us to achieve this which I will discuss in this and future posts. Let’s get straight in to it…

Flux Pattern with Redux

The Flux pattern is based on a unidirectional data flow for state changes within an application. The whole concept in one line is “data flows in one direction”. Simply put if a component needs to change some state, it calls an action, this action has a type and payload, type being the type of action and payload being the data which is needed to update the relevant state. The action is dispatched and picked up by a reducer (which is just a switch statement based on the action type) and then the reducer updates the state in the store accordingly

The main concepts in the Redux implementation of Flux are:

  1. Actions – An action basically describes which state should change in response to a change such as UI action or api call. When a user carries out an action such as clicking on a button a component (connected to redux) containing the onClick handler will dispatch an action describing what has just happened the action is then dispatched to a reducer and based on the data contained in the action the correct state will be updated. Actions are objects with two properties, the first is a type which is the type of action taking place and the second property is the payload which contains data the reducer uses to change the state. Actions are also where you can make api calls for data, you must use a middleware such as thunk to be able to achieve async actions, allowing you to dispatch an action which fetches data from an endpoint and dispatch another action when it returns depending on whether the request was successful or not.Example:

        {
           type: SELECT_ELECTION,
           payload: {id: '123456'},
        };
  2. Dispatcher – a dispatcher is used (as the name suggests) to dispatch actions so that they can be picked up by a reducer.

  3. Reducers – Reducers are simply switch statements which take an action from the dispatcher and depending on the type of the action carry out changes on the state using data. The state change is then propagated to all interested components. You usually have more than one reducer in your application and it is good practise to split your reducers up into ui reducers and business logic components, to keep the state as decoupled as possible. So you would have a UI reducer to handle UI state changes such as button click, check box selected etc and have a business reducer for handling data changes due to calls to restful api.Example:

    switch (action.type) {
        case SELECT_ELECTION:
            return selectElection(action, state);
        case SELECT_ELECTION_SUCCESSFUL:
            return selectElectionSuccessful(action, state);
        case SELECT_ELECTION_UNSUCCESSFUL:
            return selectElectionUnsuccessful(action, state);
        default:
            return state;
  4. Selectors – Selectors are not necessarily part of the Redux  data flow, you don’t have to use them but I have included them here because I have found they are extremely useful, and a most have in my opinion. Selectors are basically getters for your state, they are functions that take the Redux state and return data to the calling component. The data maybe taken straight from the state untouched and passed or there may be some transformation done such as filtering elements. We use reselect library for our selectors and it gives use the benefit of memoization which means that if a selector is called with arguments equal to the arguments which were previously passed then it returns a cached result and doesn’t do any unnecessary processing on the data.Example:

    const getElections = (state) => {
        return state.elections;
    };

    const getSelectedElectionId = (state) => { return state.selectedElectionId; };

    export const getSelectedElection = createSelector( [getElections, getSelectedElectionId], (elections, selectedElectionId) => elections.find((election) => election.id === selectedElectionId)) );

Below diagram shows the flow of data:

Container/Presentation Pattern

The Container/Presentation Pattern, or as it is also known as the Smart/Dummy Component Pattern is leveraged highly within our platform code base. It is hands down one of my favourite patterns, I have worked on a number of large frontend projects using different frameworks or in some cases just plain old vanilla JavaScript and have found (as we all have I am sure) that a major issue is being able to pass state where it is meant to go without it all becoming a mess and being impossible to keep track of. How this pattern works is we have a “Container” component which holds state and manages actions of its children which are “Presentation” components. Presentation components at their simplest form take in props and render html they hold no state (they are basically functions which take parameters and return html). If an action is carried out in a presentation component, such as a button click then a function passed by the Container component as a prop is called and the Container updates the state or carries out some other related action. At Modern Democracy we have the containers connected to our Redux store which calls actions to update the correct state and then the state change is passed out to all relevant components. The benefit of this pattern is all your core logic and state for a given component is contained in one place and because the children components just take the data and render html it is easier to modify, test and swap out these components when you have to.

As you can see from the diagram below which illustrates a very basic example the Container component has the event handlers and the state, it passes theses to the Presentation component in the form of props. When a user clicks on the button the click event handler is called which updates the container state and in turn this updates the Presentation component props. This keeps the flow and control of data very clean and clear.

Conclusion

As you can probably tell I am a fan of React and enjoy working with it, it of course is not without its faults which I will discuss in future posts but the benefits of the framework definitely out way the faults. Here at Modern Democracy we definitely believe that React has been the right choice for us and in the next instalment of this series I will continue to discuss patterns and techniques we have used to help develop our platform.

2018-08-03T11:42:52+00:00