Redux PDF
Redux PDF
#redux
Table of Contents
About 1
Remarks 2
Versions 2
Examples 3
Installation or Setup 3
Examples 6
Redux-thunk: basics 6
Middleware 7
Action creators 7
Syntax 10
Parameters 10
Examples 10
Provider 10
Parameters 13
Remarks 13
Examples 13
Full example 13
index.html 13
index.js 13
Chapter 5: Reducer 15
Remarks 15
Examples 15
Basic reducer 15
Using Immutable 16
Examples 18
Redux + Mocha 18
Credits 20
About
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: redux
It is an unofficial and free redux ebook created for educational purposes. All the content is
extracted from Stack Overflow Documentation, which is written by many hardworking individuals at
Stack Overflow. It is neither affiliated with Stack Overflow nor official redux.
The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.
Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to [email protected]
https://riptutorial.com/ 1
Chapter 1: Getting started with redux
Remarks
Redux is a JavaScript library that implements state container of the Flux-based architecture.
Main parts:
• store constructor
• store.dispatch(action)
• middleware
• reducers
Redux is astonishingly simple. It uses a function called a reducer (a name derived from the
JavaScript reduce method) that takes two parameters: An action, and a next state.
The reducer has access to the current (soon to be previous) state, applies the given action to that
state, and returns the desired next state.
Reducers are designed to be pure functions; meaning, they produce no side effects. If you pass
the same input values to a reducer 100 times, you will get the exact same output value 100 times.
Nothing weird happens. They are completely predictable. As someone with a prominent "NO
SURPRISES" sticky note on my monitor, this is a wonderful idea to contemplate.
Reducers do not store state, and they do NOT mutate state. They are passed state, and they
return state. This is what reducers look like in action. http://redux.js.org/docs/basics/Reducers.html
Reference: http://redux.js.org/docs/introduction/Motivation.html
Versions
v3.6.0 2016-09-04
v3.5.0 2016-04-20
v3.4.0 2016-04-09
v3.3.0 2016-02-06
https://riptutorial.com/ 2
Versions Release Date
v3.2.0 2016-02-01
v3.1.0 2016-01-28
v3.0.0 2015-09-13
v2.0.0 2015-09-01
v1.0.0 2015-08-14
Examples
Installation or Setup
Basic installation:
<html>
<head>
<script type="text/javascript" src="/path/to/redux.min.js"></script>
</head>
<body>
<div id="app"></div>
<script>
// Redux is available as `window.Redux` variable.
</script>
</body>
</html>
Npm installation:
Next, to use redux, you need to require it (assuming you are using module bundler, like webpack):
https://riptutorial.com/ 3
import redux from 'redux';
HTML:
<p>
<span>Counter State</span><br />
(<em>Will increase each minute</em>):
<p>
<span id="counter-state" style="font-weight: bolder"></span>
</p>
</p>
<p>
<button id="increment-action">+ Increase +</button>
<button id="decrement-action">- Decrease -</button>
</p>
REDUX LOGIC:
const {
createStore,
applyMiddleware
} = Redux
https://riptutorial.com/ 4
// ------------------------ reducers ------------------------
// those will be creating new states and returning it,
// depending on the dispatched actions
addReducer(reducers, 'INCREMENT', (state, action) => ++state)
addReducer(reducers, 'DECREMENT', (state, action) => --state)
const DEFAULT_STATE = 0
console.log(createStore)
//
// IMPORTANT BINDING:
//
// store will be dispatching the new state to the render method each time the state changes
//
store.subscribe(render)
//
// render with the state for the first time
//
render()
https://riptutorial.com/ 5
Chapter 2: Asynchronous Data Flow
Examples
Redux-thunk: basics
While redux itself is entirely synchronous, you can use a middleware such as redux-thunk to handle
asynchronous actions.
This allows you to pass a thunk to dispatch instead of a plain object. The middleware will
recognize the thunk and call it. The thunk takes the store's dispatch method as a parameter:
https://riptutorial.com/ 6
store.dispatch(loadUser(123));
This will result in an initial USER_LOADING action being dispatched, which can be used to display a
loading indicator (if so desired), and after the response has been received either a USER_LOADED
action or USER_LOAD_ERROR action will be dispatched, depending on the result of the $.ajax request.
Middleware
Middleware is what enables you to delay dispatching or even dispatch different actions in the
middle. I.e. middleware makes your asynchronous actions look synchronous.
Action creators
Another approach to handling asynchrony in Redux is to use action creators. In Flux, action
creators are special functions that construct action objects and dispatch them.
myActionCreator(dispatch) {
dispatch({ type: "ASYNC_ACTION_START" });
setTimeout(() => {
dispatch({ type: "ASYNC_ACTION_END" });
}, 1000)
}
Custom middleware:
https://riptutorial.com/ 7
export default function clientMiddleware() {
return ({dispatch, getState}) => {
return next => action => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
return actionPromise;
};
};
}
function formatUrl(path) {
const adjustedPath = path[0] !== '/' ? '/' + path : path;
return adjustedPath;
}
if (params) {
request.query(params);
}
if (data) {
request.send(data);
}
https://riptutorial.com/ 8
}
import 'whatwg-fetch';
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
}
const error = new Error(response.statusText);
error.response = response;
throw error;
}
function parseJSON(response) {
return response.json();
}
https://riptutorial.com/ 9
Chapter 3: How to link redux and react
Syntax
• <Provider store>
• connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
Parameters
Argument Description
Examples
Provider
To easily link your Redux store to your React components you can use an additional library: react-
redux.
First, you need to wrap your app in a Provider, which is a component that passes your store to be
used by child components:
After you wrapped your app into provider you can use connect function to subscribe your
component to store changes and provide mapping between Redux state properties and React
components' properties:
https://riptutorial.com/ 10
const mapStateToProps = (state, ownProps) => ({
data: state.myComponentData
});
connect(mapStateToProps)(MyComponent);
In your redux store you hold the raw data. Some times the raw data is all you need, but other
times you need to derive new data from the raw data, often by combining parts of the raw data.
A common use case for deriving data is filtering a list of data based on a criteria, where both the
list and the criteria may be changed.
The following example implements mapStateToProps and filters a list of strings to keep those who
match a search string, producing a new prop filteredStringList that can be rendered by a React
Component.
return {
filteredStringList: stringList
.filter(string => string.indexOf(searchString) > -1)
};
}
To keep the reducers simple you should only hold the list of data and the filtering criteria in the
store, which means you need to derive the data on read time (like we did in the example above).
The solution is to use memoized selectors that are defined only once. The React community
suggests using the npm library reselect to create memoized selectors. In the example below we
achieve the same result as in the first example, only with memoized selectors.
https://riptutorial.com/ 11
);
Note that the two first selectors getStringList and getSearchString are not memoized, because
they are so simple that it would provide no performance gain. They still need to be created
because we need to pass them as dependencies to createSelector, so that it knows when to reuse
the memoized result and when to compute a new result.
The memoized selector will use the function passed as the last argument passed to createSelector
to compute the derived data (in our example the function that returns the filtered string list). Each
time the memoized selector is called, if the dependencies are not changed since the last time it
was called, (in our example stringList and searchString), the memoized selector will return the
previous result, saving the time it would take recompute it.
You can think of selectors (memoized or not memoized) as getters for the store state, just like
action-creators are setters.
You can find more examples on computing derived data in the Redux documentation's recipes
section.
https://riptutorial.com/ 12
Chapter 4: Pure Redux - Redux without any
framework
Parameters
Paramenter Description
It must be an object with at least the type property. Any other property can be
action
passed and will be accessible within the reducer function.
Remarks
If you're not using bundlers like Webpack and Browserify, change the first line to:
Or just call it directly from the Redux global when creating the store:
Examples
Full example
index.html
<button id="increment">Increment</button>
<button id="decrement">Decrement</button>
<p id="app"></p>
index.js
case 'DECREMENT':
return state - 1;
default:
return state;
https://riptutorial.com/ 13
}
}
function render() {
const state = store.getState();
document.querySelector('#app').innerHTML = `Counter: ${state}`;
}
incrementButton.addEventListener('click', () => {
store.dispatch({ type: 'INCREMENT' });
});
decrementButton.addEventListener('click', () => {
store.dispatch({ type: 'DECREMENT' });
});
store.subscribe(() => {
render();
});
render();
https://riptutorial.com/ 14
Chapter 5: Reducer
Remarks
Reducers change the application state based on the actions fired.
The state is immutable, that means reducers should be pure: for the same input, you should
always get the same output. Because of this, mutability is forbidden in reducers.
Examples
Basic reducer
// Add only one entity. Again, note how we make a new entities array
// combining the previous one with the new entity
// instead of directly modifying it, so we don't mutate the state.
case ACTION_ENTITY_CREATED:
return Object.assign({}, state, {
entities: [action.entity].concat(state.entities)
}):
// If the action is not relevant to this reducer, just return the state
// as it was before.
https://riptutorial.com/ 15
default:
return state;
}
};
Using Immutable
Immutable is a great library that provides us with immutable versions of widely used types of
collections, such as Lists, Stacks, Maps, and more.
It simplifies the manipulation of the state and makes it easier to make pure calculations and avoid
mutation.
Let's see how the Basic reducer can be rewritten using Immutable's Map and List structures:
// Import Immutable
import Immutable from 'immutable';
switch(action.type) {
case ACTION_ERROR:
return state.set('error', action.error);
case ACTION_ENTITIES_LOADED:
return state.merge({
entities: Immutable.List(action.entities)
error: undefined
});
case ACTION_ENTITY_CREATED:
return state.set('entities', state.entities.push(action.entity));
default:
return state;
}
};
As you may have seen, handling the immutable state gets easier using Immutable.
https://riptutorial.com/ 16
// Set up a default state
const initialState = {
error: undefined,
entities: [],
loading: true
};
// Add only one entity. We will use spread operator (...) to merge
// objects properties and to create new entity
case ACTION_ENTITY_CREATED:
return {
...state,
entities: [action.entity].concat(state.entities)
};
https://riptutorial.com/ 17
Chapter 6: Testing Redux apps
Examples
Redux + Mocha
Action creator:
describe('actions', () => {
it('should show sidebar', () => {
const expectedAction = {
type: type.SHOW_SIDEBAR
}
expect(actions.showSidebar()).toEqual(expectedAction)
})
})
https://riptutorial.com/ 18
expect(store.getState().test).to.equal(0);
https://riptutorial.com/ 19
Credits
S.
Chapters Contributors
No
Getting started with 1ven, Arijit Bhattacharya, Community, Inanc Gumus, jpdelatorre
1
redux , Random User, uddhab, Vanuan
Asynchronous Data Ali Sepehri.Kh, Arijit Bhattacharya, Franco Risso, Ming Soon,
2
Flow rossipedia, Vanuan
https://riptutorial.com/ 20