Using redux with FuseJS


#1

Most of the users know hot to use redux, when it’s good, and when it’s not.
FuseJS provides us with observables, which are extremely good for any state management.

But I prefer to have predictable and immutable global state, and redux can solve this problem.

So, first of all, let’s create a new project and add redux package from npm.

        npm init .
        npm install redux --save

Now, let’s get into store configuration:

store.js
import {
  createStore,
  combineReducers
} from "node_modules/redux/dist/redux.js";

// our dumb reducer
function counter(state = 0, action) {
  switch (action.type) {
    case "INCREMENT":
      return state + 1;
    case "DECREMENT":
      return state - 1;
    default:
      return state;
  }
}
//use combineReducers to make sure, we support this redux feature
const reducers = combineReducers({
  counter: counter
});
//export our store, so that we able to get it inside other components
export const store = createStore(reducers);

Now, let’s create a basic redux-connected class, so that we can reuse it in our components:

import {store} from '../store';

export default class ReduxComponent {
    constructor(mapStateToProps) {
        // this is the function, which will take state and give us actual props
        this.mapStateToProps = mapStateToProps;
        // with this, in other classes we can just call this.dispatch to emit action
        this.dispatch = store.dispatch.bind(store);
        // get initial props
        this.updateProps(store.getState());
        // subscribe to store changes
        store.subscribe(()=>{
            this.updateProps(store.getState());
        })
    }
    // this will make props field immutable
    updateProps(state) {
        this.props = Object.assign({},this.props, this.mapStateToProps(state));
    }
}

Now, let’s create our actual model

import ReduxComponent from 'fuse-redux/ReduxComponent';

export default class TodoApp extends ReduxComponent {
  // this is function we gonna use to map state to props
  static mapStateToValues(state) {
    return {
      counter: state.counter,
    };
  }
  constructor() {
    super(TodoApp.mapStateToValues);
  }

  increment(title) {
    this.dispatch({ type: "INCREMENT" });
  }
  decrement(title) {
    this.dispatch({ type: "DECREMENT" });
  }
}

And here we go, let’s create our first redux-connected UX Component:

<App Model="TodoApp">
  <Panel>
    <StackPanel>
      <Text Value="{props.counter}"/>
      <Button Clicked="{increment}">
        <Text Value="Increment" />
      </Button>
      <Button Clicked="{decrement}">
        <Text Value="Decrement" />
      </Button>
    </StackPanel>
	</Panel>
</App>

There is also a way to use redux-logger and possibly redux-dev-tool.