Load Data from REST API

How to load data from a REST API to then display it inside a component? This is achieved inside the ComponentDidMount for class components and inside a call to useEffect() without parameters in functional components.

useEffect(() => {
console.log('useEffect()');
getRESTData();
console.log('useEffect() done');
}, []);

There is one important thing to know! ComponentDidMount and the empty effect are called after the components are rendered for the first time. In other words, components are rendered with empty data initially!

Make sure to design your components so that they deal with empty data without throwing any errors!

When ComponentDidMount or the empty effect have been executed and the data is finally available, the components are rendered again and this time around do have access to the REST data. Design your components in a way that they deal with data arriving at a later point in time!

Testing with Jest

The Redux Documentation declares Jest as the unit testing framework of choice. This is a beginners introduction to Jest.

Taken from the Jest documentation:

Zero configuration – Jest is already configured when you use create-react-app or react-native init to create your React and React Native projects. Place your tests in a __tests__ folder, or name your test files with a .spec.js or .test.js extension. Whatever you prefer, Jest will find and run your tests.

As it turns out, Jest is already integrated into your codebase should you have used create-react-app.

Error fsevents unavailable

When npm run fails with the following output:

npm test

> cryptofrontend@0.1.0 test /Users/bischowg/dev/react/cryptofrontend
> react-scripts test

Error: `fsevents` unavailable (this watcher can only be used on Darwin)
    at new FSEventsWatcher (/Users/bischowg/dev/react/cryptofrontend/node_modules/sane/src/fsevents_watcher.js:41:11)
    at createWatcher (/Users/bischowg/dev/react/cryptofrontend/node_modules/jest-haste-map/build/index.js:780:23)
    at Array.map (<anonymous>)
    at HasteMap._watch (/Users/bischowg/dev/react/cryptofrontend/node_modules/jest-haste-map/build/index.js:936:44)
    at _buildPromise._buildFileMap.then.then.hasteMap (/Users/bischowg/dev/react/cryptofrontend/node_modules/jest-haste-map/build/index.js:355:23)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:160:7)
npm ERR! Test failed.  See above for more details.

read https://github.com/expo/expo/issues/854

npm r -g watchman
brew install watchman

I had to run the brew command three times before it finally worked. npm test should now work without issues.

Testing Action Creators

Given a file actions.js that contains the action creator

function receiveEntriesActionCreator(json) {
  return {
    type: RECEIVE_ENTRIES,
    entries: json
  }
}

you want to write a test that verifies that the action creator returns an action that has a type property with a value of RECEIVE_ENTRIES and an entries property that contains a specific javascript object.

In order to write the test, add a file called actions.test.js next to actions.js. In actions.test.js insert:

import * as actions from './actions.js';

import {
  RECEIVE_ENTRIES,
  ADD_ENTRY,
  UPDATE_ENTRY,
  DELETE_ENTRY
} from './actions.js'

test('receiveEntriesActionCreator returns a correct action', () => {

  const entries = [{ id: '12345', password: 'abcdef' }]

  const expectedAction = {
    type: RECEIVE_ENTRIES,
    entries
  }

  expect(actions.receiveEntriesActionCreator(entries)).toEqual(expectedAction)

});

On line 10, the test() function is called given a description of what the test is trying to verify. The second parameter is the code that the test should execute. Lines 12 to 17 assemble the expected result. On line 19, expect().toEqual() is called.

In the console type npm run to start a watcher that executes the tests after you save your changes to a file that has a unit test.

React Redux Cryptofrontend

This post describes how the Cryptofrontend was created.

Description of the Crypto-Application

The cryptoapp stores password entries in a server (which for this post is assumed to be working prerequisit) and it has a frontend that displays the entries to the user. The frontend will look very similar to an email client. On the left it lists all entries. The entries in the list are only showing part of the information so the user can quickly decide which entry he wants to use. Once the user clicks one of the entries, the entire data of that entry will be displayed on the right side of the application in a details view.

Basic CRUD operations on the password entries will be possible. If the user enters the master password in the details view, the password will be decrypted and copied into the users clipboard if that is possible. Otherwise the app just displays the plaintext password for the user to copy. The decryption and encryption happens in the user’s browser. Only encrypted data is transmitted to and from the backend.

Creating the Project Structure

Update node using the node version manager (nvm) to the latest version, otherwise the later steps probably will fail. First find the latest version using nvm ls-remote. Then install that version using nvm install <version>. nvm will automatically make installed version current so it is used when executing npm and node commands.

The first step is to generate the empty project structure using create-react-app command.

npx create-rect-app cryptofrontend

Make sure that the generation did finish successfully! The generator will create a cryptofrontend folder which can be opened in Visual Studio Code. If type yarn start inside the project folder, a server will be started and the site is automatically opened in a browser.

Organizing the Code

All actions and thunk functions go into the action folder. The action folder will contain all objects that can be dispatched. A better name for the actions folder would be dispatcheables.

All reducers go into the reducers folder.

The store creation goes into the store folder.

Installing the required npm Packages

npm i cross-fetch
npm i redux
npm i react-redux
npm i redux-logger
npm i react-thunk
npm i redux-thunk

Defining the Redux State

First let’s define what state the Redux container will contain. This is an example JavaScript Object that outlines what the state comprises. There is the id of the currently selected password entry. If no entry is selected, the value will not be there at all or it will be equal to or less than zero. After the selected id, there is an array of objects, each denoting one password entry.

{
  selected_entry_id: 1,
  entries: [
    {
      id: 1,
      password: 'ad2jd92jd9dj9j9'
    },
    {
      id: 2,
      password: 'sdfsdfsfsfsdfsdf'
    }
  ]
}

Retrieving Entries from the Server

Let’s develop the application in an iterative fashion by adding little bits of functionality until the app is complete. That way the entire complexity will not hit as as hard. In a sense this allows us to apply the principle of divide and conquer.

The first iteration will retrieve entries from the server and output the entries to the developer console. The entries have to be fetched from the backend and they have to be stored in the Redux store. Normally to alter the store, an action has to be dispatched and a reducer will create the new state given the current state and the values contained in the action. In order to talk to a backend, instead of dispatching an action and defining a reducer, the thunk middleware is used which makes it possible to dispatch a function.

This function is called fetchEntries(). Once fetchEntries() did receive the entries from the server, it will dispatch an action that carries the entries retrieved from the backend. This action will be handled by a reducer that inserts the entries into the state.

Reducers

Lets first talk about the reducers. As the first iteration only cares about the entries, there is only one reducer that insert entries into the store. The root reducer will only consist of this one reducer.

import { combineReducers } from 'redux'
import {
  RECEIVE_ENTRIES
} from '../actions/actions.js'

// deals with entries
function entriesReducer(state = {}, action) {

  // switch over all action types
  switch (action.type) {

    // entries were retrieved from the backend
    case RECEIVE_ENTRIES:

      // this reducer will take the entries from the action and put copy
      // them into the store
      return Object.assign({}, state, {
        entries: action.entries
      })

    default:
      return state
  }
}

The entriesReducer only reacts to the RECEIVE_ENTRIES action and it will just copy the entries that the action contained into the store. The file also builds the root reducer:

// build the rootReducer from several partial reducers
const rootReducer = combineReducers({
  entriesReducer
});

// default export of this file
export default rootReducer;

The root reducer currently only consists of the entriesReducer because there is no other reducer right now. (A currentlySelectedEntryReducer will follow in upcoming iterations).

The next thing needed is the RECEIVE_ENTRIES action itself.

Actions, Thunks and other Dispatcheable Objects

import fetch from 'cross-fetch'

export const RECEIVE_ENTRIES = 'RECEIVE_ENTRIES'

// this function is called an action creator as it constructs
// and returns an action
function receivePostsActionCreator(json) {
  console.log('receivePostsActionCreator ', json);
  return {
    type: RECEIVE_ENTRIES,
    entries: json
  }
}

// this function is a thunk. It is dispatcheable and performs
// the server communication. Once it is done, it will dispatch
// call the action creator to dispatch the RECEIVE_ENTRIES action
export function fetchEntriesThunk() {
  console.log('fetchEntriesThunk');
  return dispatch => {
    return fetch(`http://localhost:8081/todos`)
      .then(response => response.json())
      .then(json => dispatch(receivePostsActionCreator(json)))
      .catch((error) => {
        console.log("reset client error-------", error);
      });
  }
}

This file contains one action creator and one thunk. The thunk will use the action creator to dispatch the RECEIVE_ENTRIES action once it has retrieved all entries from the backend. The entries are put into the RECEIVE_ENTRIES action by the action creator. The action is dispatched and handled by the reducer defined in the last section. The reducer will create a new state from the entries contained in the action. This is how the entries travel from the backend all the way into the store.

Store Creation

This file creates a store and adds the thunk and logger middleware:

import rootReducer from '../reducers/reducers.js';
import { createStore, applyMiddleware } from 'redux'
import thunkMiddleware from 'redux-thunk'
import { createLogger } from 'redux-logger'

const loggerMiddleware = createLogger()

function configureStore(preloadedState) {
  return createStore(
    rootReducer,
    preloadedState,
    applyMiddleware(thunkMiddleware, loggerMiddleware)
  )
}

export default configureStore;

The configureStore() function is exported. It creates the store and adds the rootReducer. It also allows to add an optional initial state, which we do not use. Also, it applies middleware. It applies the thunk middleware which allows for dispatching functions instead of only action objects. It applies a loggerMiddleware which logs every state change to the developer console.

In the app.js file, testing code is added. The testing code will also fulfill all our goals that we set for the first iteration. It creates the store, dispatches the thunk and by doing so, retrieves data from the server and inserts that data into the store.

import configureStore from './store/store.js'
import { fetchEntriesThunk } from './actions/actions.js'

// create a store
const store = configureStore();

// Log the initial state
//console.log(store.getState());
store.dispatch(fetchEntriesThunk());
//console.log(store.getState());

When you load the cryptofrontend in your browser, this code is executed and the backend is accessed. In the developer tools console of your browser, you should see all the state changes that the store is going through.

Summary for the First Iteration

Without using any components, the goal of the first iteration was to integrate the Redux Store to the backend server. There is now a thunk that GETs all entries from the backend.

Adding an Entry into the Redux Store

This thunk will POST an entry to the redux store:

export function addEntryThunkActionCreator() {

  // DEBUG
  console.log('addEntryThunkActionCreator');

  // return the thunk
  return dispatch => {
    return fetch(`http://localhost:8081/todos/add`, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ id: 0, password: 'Textual content' })
    })
      .then(response => response.json())
      .catch((error) => {
        console.log("POST addentry error ", error);
      });
  }
}

Note that the new entry is not added to the Redux Store, it is only posted to the backend. Given this code, the app has to dispatch the thunk that retrieves all entries to sync up its state with the backend store. An alternative would be to dispatch an action that appends the new entry to the Redux store state in the success case. This alternative saves a lot of network traffic. The following code defines an action to append a new entry to the Redux store.

Selecting an Entry in the Redux Store

The next iteration will add an action for selecting one of the entries. The idea is that after selecting an entry, the details view has to render all the entries details. The currently selected item is actually part of the state in the store. That is why the store will be extended by an action for selecting an entry. Thanks for reading and stay tuned for the next iteration.

Building the components

 

React Redux Development

For a beginner, it can be very confusing to create a React Redux app as a lot of new concept have to be understood and combined before anything sensical can be built. This post is supposed to sketch out a process for getting a React Redux app up and running in a controlled manner.

The steps are ordered from the backend towards the frontend of the application. Starting from the backend that exposes a API, the Redux model/container and then finally the React components in the frontend are created.

Creating the Backend

  1. Create the database schema in a database
  2. Create a node server using express

Creating the Redux Part

  1. Define the JavaScript Object that describes the applications state
  2. Define the actions that can be performed on the state
  3. Define the action creators that create the actions
  4. Define the reducers for the actions. The default value of the reducers state parameter defines the initial state of the Redux Container.
  5. Define the root reducer as a combinedReducer from all reducers.
  6. Define thunk reducers that retrieve data from the backend
  7. Create the container with the initial state
  8. Write a test for the entire Redux part of the application

Creating the React Part

  1. Define the components. Define what properties the components have that means, what properties the components take the data from when rendering the GUI. The properties of the component act as the interface of the component. It is the task of the React-Redux mapStateToProps Method to adapt the Redux container state to the props of the component
  2. Connect the components to Redux using Redux-React. Use mapStateToProps to map the Redux container state to the components properties.

React Redux Fetch Data from an API with Redux Thunk

The GUI of a webapp oftentimes has to retrieve its data from a backend system. In this post we assume that the backend system is providing the data via an API that supports GET requests. This post rehashes the current best practices for calling a backend API and retrieving the data as described in the Redux Advanced Tutorial.

Container Pattern in React-Redux

React and Redux work together for creating the frontend part of web applications. React renders the GUI elements while Redux manages the application state.

This post is a rehash of the Redux documentation for using Redux with React.

Rational

In Redux, the application state is altered by reducers which are triggered by actions. Both actions and reducers are part of Redux. A method called dispatch() is called given an action which triggers the reducers. The state is kept in a so called Redux store. A method called connect() connects a React component to Redux.

Integrating React with Redux can be done in several ways. A basic implementation might call dispatch() directly from within the React component, tighly coupling React to Redux. Another problem with this naive approach is that the separation of concerns principle is violated. The React component now manages and renders state at the same time.

It would be nice to separate the rendering from the state management which keeps the components smaller and the responsibilities clear. A elegant solution, that is currently considered best practice is to use the Container Pattern. In order to separate the concerns, the container pattern splits one React component into a React component and a JavaScript file that manages Redux. The React component strictly displays the GUI, while the JavaScript file (called the container) manages the communication to Redux wrapping the React component. The JavaScript file will execute the connect() call on the React component.

You can think of the container as a layer that sits between the GUI React component and Redux, hiding all Redux from the GUI component. Instead of calling connect() and dispatch() from within a React component directly, the container will execute all connect() and dispatch() calls.

There is a variation of the container pattern, where the container also renders GUI elements. This is not a clear separation as defined above but the option is still available. In the Redux Todos example, the AddTodo container is an example of this variation.

Implementation

In order to implement the container pattern, following parts are needed

  1. A method that creates and returns an action (called Action Creators actually one such method per action) to send into the Redux reducers.
  2. The pure React component for rendering the GUI.
  3. The container file for talking to Redux.
  4. A Redux agnostic means for getting state from the Redux store into the React component.
  5. A Redux agnostic means for altering the Redux state from within the React component.

The following code is taken from the Redux Todos examples. Just a quick explanation of what the code is supposed to do: The Todos example allows the user to add Todo items (Strings) to a list of Todos. Clicking on one of the items marks it as completed, clicking it again marks it as active again. This is referred to as toggeling.

1. Is a function that creates and returns an action. It is called an ActionCreator:

export const toggleTodo = id => ({
  type: 'TOGGLE_TODO',
  id
})

The function toggleTodo() will return a TOGGLE_TODO action. Do not put this function into the React component as actions are Redux specific and the React component should not know anything about Redux.

2. Let’s look at the TodoList component from the Redux Todos examples. Note that there is no Redux code in the component!

import React from 'react'
import PropTypes from 'prop-types'
import Todo from './Todo'

// toggleTodo is a method that the Container has put into the properties
// using a call to mapDispatchToProps. This component should call toggleTodo
// whenever it wants to toggle a TODO item.
const TodoList = ({ todos, toggleTodo }) => (
  <ul>
    {todos.map(todo =>
      <Todo
        key={todo.id}
        {...todo}
        onClick={() => toggleTodo(todo.id)}
      />
    )}
  </ul>
)

TodoList.propTypes = {
  todos: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    completed: PropTypes.bool.isRequired,
    text: PropTypes.string.isRequired
  }).isRequired).isRequired,
  toggleTodo: PropTypes.func.isRequired
}

export default TodoList

The first property (line 8) are all the Todo items that the TodoList has to render. The container will retrieve the Todos from the Redux store and pass them into this property (explained later)

You can see (line 8) that the component has another property, the toggleTodo() property. The container puts the toggleTodo() function from stept 1. into this property after wrapping it into a dispatch() call (explained later). This is how the React component can change the Redux state without knowing about Redux. It will just call the toggleTodo() wrapped function which triggers Redux code.

3. The third part is the container

import { connect } from 'react-redux'
import { toggleTodo } from '../actions'
import TodoList from '../components/TodoList'
import { VisibilityFilters } from '../actions'

const getVisibleTodos = (todos, filter) => {
  switch (filter) {
    case VisibilityFilters.SHOW_ALL:
      return todos
    case VisibilityFilters.SHOW_COMPLETED:
      return todos.filter(t => t.completed)
    case VisibilityFilters.SHOW_ACTIVE:
      return todos.filter(t => !t.completed)
    default:
      throw new Error('Unknown filter: ' + filter)
  }
}

const mapStateToProps = state => ({
  todos: getVisibleTodos(state.todos, state.visibilityFilter)
})

// Put the method toggleTodo into the properties, so that the wrapped component
// can take it from the properties and use it. The toggleTodo implementation is 
// specific to Redux. It will call dispatch() using an action.
//
// The action is created using a method also called toggleTodo (I cannot imagine
// why the authors of this example though it was a good idea to call both functions
// the same although they are two different things!!! This will confuse beginners into oblivion)
const mapDispatchToProps = dispatch => ({
  toggleTodo: id => dispatch(toggleTodo(id))
})

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList)

The container wraps the TodoLost in a connect() call (line 34). It uses two parameters mapStateToProps() and mapDispatchToProps(). This is how the container passes parameters into the Redux component.

mapStateToProps() retrieves the Todo items (applying busines logic as in filtering the Todo items) from the Redux store and then binds them to the todos Property. The todos property then is available in the React component so it can render the Todo items. That means the React component learns about the data without knowing anyting about the Redux store. This is basically step 4. in our list of necessary items.

mapDispatchToProps() deals with step 5. It allows the React component to alter the Redux store without knowing about the Redux store. What mapDispatchToProps() does is, it binds a dispatch() function to the toggleTodo property. dispatch() calls the function from step 1. which returns a Redux action and then sends this action to the Redux store to alter it’s state.

mapStateToProps() and mapDispatchToProps() are actually methods from the official react redux binding.

At this point all five bullet points from the list are dealt with.

Summary

To recap and to summarize this post, React and Redux go together very well. In order to keep a clean code structure and follow the current best practices, the container pattern is used to integration React and Redux. A container is a JavaScript file that acts as a layer between React and Redux. The container contains all Redux specific parts and hides them from the React component that it wraps. The React component’s task is to render the GUI using the state that it gets fed from the container and to update the state using the properties that the container provides. The React component knows nothing about the container and hence it knows nothing about Redux.

As an outlook, maybe it is possible to implement a generic container that can be used to wrap all your react components. This means that you could use that container from a JS library or NPM dependency and just Redux-Enable your React component by applying that generic container to it. In Java Spring such a feature would be implemented using annotations. Maybe there is something equivalent in JavaScript?

Thank you for reading this post.