Redux

“Photography is truth. The cinema is truth 24 times per second.”
Jean-Luc Godard

Original

Resize

White balance

Cartoon

Unidirectional data flow

View

React components tree

Action

Unified way to communicate
{
  type: 'START_GAME'
}
{
  type: 'SELECT_CARD',
  payload: { id: 32 }
}

Action creator

Simple functions that create actions
export const selectCard = (id: number) => ({
    type: 'SELECT_CARD',
    payload: id
});

Reducers

The only way to create a new state
const gameReducer: Reducer = (state = initialState, action) => {
    switch (action.type) {
        case SELECT_CARD:
            return {
                ...state,
                selectedCard: action.payload,
            };
        default:
            return state;
    }
};
State is immutable!

Store

Holds the single application state
Single source of truth
export const store = createStore(gameReducer);

Redux Middlewares

  • Business logic
  • Action in - Action out
  • Piped to each other, order matters!

Middleware signature

const myMiddleware: Middleware = (store) => (next) => (action) => {
  if (action.type === START_GAME) {
    store.dispatch(actions.shuffleCards());
  } else {
    next(action);
  }
}

React-Redux


source: https://www.smashingmagazine.com/2018/07/redux-designers-guide/

source: https://www.smashingmagazine.com/2018/07/redux-designers-guide/

Providing the store

Store Provider

import { Provider } from 'react-redux';

<Provider store={store}>
  <App />
</Provider>

Accessing the store

Connect state to props

import { connect } from 'react-redux';

type PropsFromState =  Pick<GameState, 'moves'>;

const mapStateToProps = (state: GameState): PropsFromState => ({
  moves: state.moves,
});

const ConnectedCongrats = connect(mapStateToProps)(Congrats); 

use it

type CongratsProps = InnerProps & PropsFromState;

const Congrats: React.SFC<CongratsProps> = ({moves}) => 
      (<div className="score">Score: {moves}</div>);

🔥 Fire some actions

Connect actions to props

import { connect } from 'react-redux';
import * as actions from './actions';

interface PropsFromDispatch {
  startGame: typeof actions.startGame;
}

const mapDispatchToProps = (dispatch: Dispatch): PropsFromDispatch => ({
  startGame: () => dispatch(actions.startGame()),
});

const ConnectedCongrats = connect(null, mapDispatchToProps)(Congrats);

use it

type CongratsProps = InnerProps & PropsFromDispatch;

const Congrats: React.SFC<CongratsProps> = ({startGame}) => 
      (<button onClick={startGame}>Start game</button>);

🛠 Try it

  • Create a new Redux store
  • Move all logic from Game component
  • Connect the store to the app