Redux in React and Angular 2

Earlier this month I presented at dddbrisbane about simplifying UI programming and I included the simplest React + Redux application I could come up with.

The simplest React + Redux application I could come up with

It displays a random number. Clicking the text generates a new random number. Toggle the Result button to see the code more easily.

See the Pen FknRooowwwmmm by Liam McLennan (@liammclennan) on CodePen.

https://production-assets.codepen.io/assets/embed/ei.js

It uses the React function component syntax to define the component as a function from UI state (props) to HTML (a H1 tag).

function HelloNumber(props) {
  function handleClick(e) {
    store.dispatch({type:'MAKE_A_NEW_NUMBER'});
  }
  return <h1 onClick={handleClick}>A random number {props.number}h1>;
}

The onClick handler dispatches a MAKE_A_NEW_NUMBER action to the redux store.

The UI state for the application is an object with a property number:

{ number: Math.random() }

The redux reducer (function responsibile for applying actions to the state to make a new state) handles the MAKE_A_NEW_NUMBER number by setting it to a new random number.

let store = Redux.createStore(function (state = { number: Math.random() }, action) {
  switch (action.type) {
    case 'MAKE_A_NEW_NUMBER':
      return Object.assign({},state, {number:Math.random()});
    default: return state;
  }
});

Now dispatching an application has updated the state, but we still need to have state changes trigger the UI to update, which is done via the subscribe method:

store.subscribe(()=>{
  ReactDOM.render(
    <HelloNumber number={store.getState().number}  />, 
    document.getElementById('container')
  );
});

and finally prime the whole thing by an initial dispatch

store.dispatch({type:'MAKE_A_NEW_NUMBER'});

This is not strictly necessary but it is an easy way to trigger the subscribe callback and cause the initial render.

The simplest Angular 2 + Redux application I could come up with

What would the equivalent Angular 2 application look like?

I couldn’t find a simple way to develop an Angular 2 application in Codepen or similar so instead I worked locally, starting with the Angular 2 Quickstart.

To reproduce the random number display functionality in Angular 2 I found that I needed a component hierarchy (parent + child).

The child component contains the header and dispatches a NEW_RANDOM_NUMBER action when clicked, just like the React component. Two values are passed into the child component, from the parent, via @Input() decorators: the application state (appState) and the redux store dispatch function (dispatch).

import { Component,Input } from '@angular/core';

@Component({
  selector: 'my-child',
  template: `

A random number {{appState.number}}

`, }) export class ChildComponent { @Input() appState:any; @Input() dispatch: (action:any) => void; onClickMe() { this.dispatch({type:’NEW_RANDOM_NUMBER’}); } }

The parent component (AppComponent) creates the redux store, using the same reducer as the React version. The UI state is copied to a local field (appState) and updated whenever the store’s state changes. The appState and redux dispatch function are bound to the child component ().

import { Component,Input } from '@angular/core';
import { ChildComponent } from './child.component';
import { createStore } from 'redux'

interface HasANumber {
  number: number;
}
interface Action {
  type: string;
}

@Component({
  selector: 'my-app',
  template: `"appState" [dispatch]="store.dispatch">my-child>`
})
export class AppComponent  { 
  store = createStore<HasANumber>(function (state = {number:Math.random()}, action:Action) {
    switch (action.type) {
      case "NEW_RANDOM_NUMBER": 
        return {number:Math.random()};
      default: return state;
    }
  });
  appState = this.store.getState();

  constructor() {
    this.store.subscribe(()=> {
      this.appState = this.store.getState();      
    });
  }
}

Final Thoughts

Having Typescript easily available in Angular 2 was nice. Further, I found that Angular 2 is at its best when imitating my very strict React style. Both frameworks work well with Redux and the uni-directional data flow idea.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s