Skip to content

Reducers

Zach Plata edited this page May 2, 2018 · 1 revision

What are Reducers

A reducer is an entity within the Redux library that focuses on maintaining partial state of the application. It does this by initializing state values, and when incoming actions come through (with payload data), it returns a whole new state according to specific actions (i.e. when an action to set the current FHIR server comes in, it sets the currentFhirServer property in a new state). Together, reducers make up the store, which is where data for the Sandbox application is held. One reducer could handle the state for all things relating to FHIR servers, like the fhir-server-reducers.js file, while another reducer may handle state for all things concerning configured CDS Services, like the cds-services-reducers.js file. See below for an example of the state properties fhir-server-reducers.js maintains.

const initialState = {
  testFhirServer: null,
  currentFhirServer: '',
  currentMetadata: null,
  defaultFhirServer: 'https://api.hspconsortium.org/cdshooksdstu2/open',
  fhirVersion: '1.0.2',
  isDefaultFhirServer: true,
  accessToken: null,
};

Relation to Actions

A reducer will simply listens for actions that come through, and return new state that gets sent to the view components. However, it will only act on specific actions it is interested in, and this is determined by the action type. See below for an example action that may come through to the reducer.

{
  type: 'SET_TEST_FHIR_SERVER',
  fhirServer: 'http://example-test-fhir-server.com',
}

When the fhirServerReducer sees this action come through, it may be interested in setting it's own testFhirServer property in state. Since all actions come through all reducers, the Sandbox filters actions based on its action types using switch statements like below.

const fhirServerReducers = (state = initialState, action) => {
  switch (action.type) {
    case types.SET_TEST_FHIR_SERVER: {
      return Object.assign({}, state, {
        testFhirServer: action.fhirServer,
      });
    }
    . . .
  }
}

Above, we are simply making a copy of the current state object that the reducer holds, and changing the testFhirServer property to hold the value http://example-test-fhir-server.com from the action it intercepted, and returning the entire state afterwards. This state then gets emitted to all components who listen for this property in mapStateToProps and otherwise automatically.

Connecting Reducer to Store

In order for the view components to receive new state automatically when state is changed via reducers (as done above), reducers must be connected to the store. First, reducers are combined together, as seen in src/reducers/index.js, and together will make up the entire state of the application. Then, in the store file, we simply create the store with the combined reducers. See src/store/store.js for more details on this.

How to use

To add another reducer to the project, first consider if any of the new data/state can be incorporated into any of the existing reducers. If it makes sense to make a new separate reducer for the application, create a reducer file under the src/reducers/ directory. Follow the pattern of the existing reducers to get an idea of how to create the logic behind storing and updating data. Next, import the reducer to the src/reducers/index.js file to combine it with the other reducers to make the application state. Then you can start to use this data in the view components accordingly. Lastly, make sure to add tests for the reducers under the tests/reducers/ directory.