Hi!

I'm Luke

I'm a software engineer at

@luke_dot_js

@lukewestby

luke.westby@raise.com

Redux

// TODO:
  • Design of Redux
  • Philosophy of Redux
  • Building with Redux

 

"Redux is a predictable state container for JavaScript"

State

Components and stuff

Subscription

State

Components and stuff

Subscription

Action

Reducers

Dispatch

This looks like Flux!

It totally does!

Is it Flux?

No.

There is no store management or dispatch registration boilerplate, only reducers and actions

Every property of your state is expressed as a reduction of actions over time.

So, instead of doing this:

import dispatcher from '../dispatcher.js';
import { Store } from 'some-flux-lib';

class ThingsStore extends Store {

  constructor(dispatcher) {
    super(dispatcher);
    this._things = [];
    dispatcher.register(this.onDispatch.bind(this));
  }

  get things() {
    return this._things;
  }

  addThing(thing) {
    this._things.push(things);
    this.notify();
  }

  onDispatch({ type, payload }) {
    switch(type) {
      case 'ADD_THING':
        this.addThing(payload);
        break;
    }
  }
}

export default new ThingsStore(dispatcher);

And this:

import React from 'react';
import ThingsStore from '../ThingsStore.js';
import dispatcher from '../dispatcher.js';

export default React.createClass({

  getInitialState() {
    return { things: ThingsStore.things };
  },

  onChange() {
    this.setState({ things: ThingsStore.things });
  },

  componentDidMount() {
    ThingsStore.addChangeListener(this.onChange);
  },

  componentWillUnmount() {
    ThingsStore.removeChangeListener(this.onChange);
  },

  renderList() {
    return this.state.things.map((thing) => (
      <li key={thing.id}>{thing.name}</li>
    ));
  },

  addThing() {
    dispatcher.dispatch({ 
      type: 'ADD_THING',
      payload: { id: Math.random(), name: 'New Thing' }
    });
  },

  render() {
    return <div>
        <button onClick={this.addThing}>Add</button>
        <ul>{this.renderList()}</ul>
    </div>;
  }
});
            

We can do this:

import { combineReducers } from 'redux';

export function addThing(thing) {
  return { type: 'ADD_THING', payload: thing };
}

function things(state = [], { type, payload }) {
  switch(type) {
    case 'ADD_THING':
      return state.concat(payload);
    default:
      return state;
  }
}

export default combineReducers({
  things
});

And this:

import { connect } from 'react-redux';
import { addThing } from '../state.js';

const connector = connect(
  (state) => state,
  { addThing }
);

function ThingsList({ things, addThing }) {
  
  const list = things.map((thing) => (
    <li key={thing.id}>{thing.name}</li>
  ));

  return (
    <div>
      <button onClick={addThing}>Add</button>
      <ul>{list}</ul>
    </div>
  );
}

export default connector(ThingsList);

State

Components and stuff

Subscription

Action

Reducers

Dispatch

The reducer signature

function (accumulator, nextValue) {

}

State is not a bunch of models, collections, and event notifications happening all over the place

 

It is an accumulation of updates over time.

Using Redux 101

React.js Chicago Meetup - Redux

By lukewestby

React.js Chicago Meetup - Redux

Overview and demonstration of Redux for the React.js Chicago Meetup on September 30, 2015

  • 1,354