Redux - peter-mouland/react-lego-2017 GitHub Wiki

https://github.com/peter-mouland/react-lego/compare/redux

Redux, for me is the go to tool when talking about managing state. In the past I tried pure flux, then alt, but Redux seems to have the edge. Redux is as a very small footprint for what it helps you achieve and it comes with many useful short-cuts and helpers.

To get started with Redux, Dan's great set of videos on egghead.io are a must: https://egghead.io/lessons/javascript-redux-the-single-immutable-state-tree.

## How's the app changed?

Before Redux, we had a client side call to an external API to fetch data. This is fine if the data doesn't have any business logic that needs to be applied before it should be displayed. So the first thing we should do is setup our API within the app on the server which will enable use to handle any data collation or database manipulation.

The larger bit of work is to setup Redux with the configured store, actions, reducers and finally update our containers to connect to the store.

Setting up the API

In the base app, our client would make all the calls to the external API in order to get the data. It's already in it's own function so to move it to it's own file for the API to use is a small task.

// Game.js -> fetchCards.js
...
fetchCards() {
  const dealtCards = randomRange(1, DECK, 2);
  const promises = dealtCards.map(cardId => json.get(`//swapi.co/api/people/${cardId}/`));
  return Promise.all(promises).then(cards => {		
    this.setState({
      people: cards,
      dealing: false		
    });		
  });
}

Our server will need another entry point for the API, routingApp.use('/api', apiRouter), and our apiRouter will handle all the logic which end-points will be available.

// server/api/index.js
import express from 'express';
import bodyParser from 'body-parser';
import fetchCards from './fetch-cards';

const apiRouter = new express.Router();
const sendStatus = (code, res, results) => res.status(code).send(results);

apiRouter.use(bodyParser.json({ limit: '1mb' }));
apiRouter.use(bodyParser.urlencoded({ limit: '1mb', extended: true }));

apiRouter.get('/game/:gameType(people|films)/:card1/:card2', (req, res) => {
  const cards = [req.params.card1, req.params.card2];
  fetchCards(req.params.gameType, cards)
    .then((results) => sendStatus(200, res, results))
    .catch((e) => sendStatus(500, res, e));
});

apiRouter.use('*', (req, res) => {
  const e = new Error();
  e.name = 'APIError';
  e.message = 'API Route Not Found';
  res.status(404).json({ error: e });
  res.end();
});

apiRouter.use(function errorHandler(err, req, res) {
  const e = new Error();
  e.name = err.name;
  e.message = err.message;
  e.stackd = err.stack;
  res.status(err.status || 500).json({ error: e });
  res.end();
});

export default apiRouter;

Setting up Redux

tbc

To see all code changes: see https://github.com/peter-mouland/react-lego/compare/redux