Redux from scratch

In my post earlier today, I posted resources regarding this new flux-inspired library called Redux. After playing around with their two examples, I think I have a good idea of how it works now and I'd like to basically re-explain the library in my own words for two reasons: 1) it will help me solidify my understanding and 2) the docs for Redux is pretty good but is still a work-in-progress.

Redux essentially gently nudges you to a more a functional way of doing Flux-esque architecture which enables neat developer tools like their hot-loading / time machine as discussed in the video. Many more benefits are outlined by the author here.

State is in Dispatchers, Not Stores

The first place to start is to understand that all the state is now managed by the dispatcher and not the individual stores. The stores instead become essentially a collection of functions to update the state.

The app bootstraps from this:

Top-level Components get State from the Store

https://github.com/gaearon/redux#smart-components

I'm calling it top-level components to be more descriptive but technically it doesn't have to be top-level. You can also just think of these as the "stateful components".

So what's happening here is that the Connector is a parent component that's basically picking which state to get. Then, in the renderChild, the first parameter is the state that you have selected, and the second is a callback function for the dispatcher. You then do bindActionCreators, which binds the action creators to the dispatcher. You can see how it's implemented in the bindActionCreators.js file which is only 7 lines.

export default class TodoApp {
  render() {
return (
<Connector select={state => ({ todos: state.todos })}>
{this.renderChild}
</Connector>
);
}

renderChild({ todos, dispatch }) {
const actions = bindActionCreators(TodoActions, dispatch);
return (
<div>
<Header addTodo={actions.addTodo} />
<MainSection todos={todos} actions={actions} />
</div>
);
}
}
So where does this state.todos get defined? It's in the stores!

Stores set initial state and then take in state from then on

Below is a store from the counter example in the repo. Here you are changing the state. This is where you can use immutable.js so you are not mutating the current state object.

import { INCREMENT_COUNTER, DECREMENT_COUNTER, INCREMENT_COUNTER_BY_THREE } from '../constants/ActionTypes';

export default function counter(state = 0, action) {
switch (action.type) {
case INCREMENT_COUNTER:
return state + 1;
case INCREMENT_COUNTER_BY_THREE:
return state + 3;
case DECREMENT_COUNTER:
return state - 1;
default:
return state;
}
}

Child (state-less) components hook to actions

I've pasted below a simplified version of the TodoItem from the TodoMVC example. Here, I've created an action to move a to do item to the top of the list, if you click on the "Move Up" link. The link triggers the moveTodoUp action which is passed into it from its parent component (and originates from the Top-level component where we did the bindActionCreators.

export default class TodoItem extends Component {
  static propTypes = {
moveTodoUp: PropTypes.func.isRequired
};

render() {
const {todo, markTodo, deleteTodo, editTodo, moveTodoUp} = this.props;
}

return (
{element} <a style={willStyles} onClick={()=>moveTodoUp(todo.id)}>Move up</a>
);
}
}

A simple action

The moveTodoUp action that you saw earlier is defined here in the ActionCreators file. It's pretty simple, all it does is return a type and what it was passed in.

export function moveTodoUp(id) {
  console.log("moveTodoUpId", id)
return {
type: types.MOVE_TODO_UP,
id
};
}

Conclusion

Overall, it was fun learning this library. I think it has some interesting concepts and the learning curve wasn't too bad. I think the docs can be organized a little better and have a few more examples (the TodoMVC and counter examples were great, so maybe including snippets from those in the docs itself). The one suggestion I would have is to see whether you can use the ES6 global symbol registry instead of having a separate file to write down constants for action strings.
views