Redux Principles
Manage the state of an application. Enhancement of the flux framework/concept for managing the state in react components.
Three principles of redux
-
The state/state-tree …
… is a single immutable state as javascript object
- Change state —> Dispatch an action
Application state is stored in one big javascript object. The state is read-only! Only dispatched (“versendete”) actions can change the state.
Any data which gets into the redux application, gets there by actions!
- Reducer —> function which does state mutations
State mutations in the app have to be described by pure functions = previous state + dispatched action = next state of app.
Pure function but with references to properties of the former state for stuff which hasn’t changed. —> makes redux fast!
How to build a redux app
reducer.jscreateStoreinindex.js: Confusing naming: Thestoreis the reduxstate
Methods on the store
store.getState();
store.dispatch({ type: 'INCREMENT' });Print to console vs. render to body
-
console.log()console.log(store.getState()); -
update, i.e. render ui to reflect current state
Register a callback anytime the particular action is dispatched
const render = () => { document.body.innerText = store.getState(); }; store.subscribe(render); render(); // render the initial state document.addEventListener('click', () => { store.dispatch({ type: 'INCREMENT' }); });
Side note: Pure functions vs. impure functions
- Pure functions: No side-effects, return new objects
- Impure functions: Can contain side-effects, e.g. calls to external APIs
Links
Great tutorial videos for Redux
Mini Redux implementation
Load script in html or add with npm.
Reduce function
const counter = (state = 0, action) => {
switch (action.type) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
default:
return state;
}
};Changing state by dispatching actions
const { createStore } = Redux;
const store = createStore(counter);
console.log(store.getState());
store.dispatch({ type: 'IINCREMENT' });
console.log(store.getState());Render to body with .subscribe(). Calls a callback everytime an action is dispatched.
const render = () => {
document.body.innerText = store.getState();
};
store.subscribe(render);
render(); // get initial count of 0
// Using naive event handler (not react or similar)
document.addEventListener('click', () => {
store.dispatch({ type: 'INCREMENT' });
});Redux error handling
Different ways of handling errors in Redux
Errors object which gets filled with all occurring errors
const INITIAL_STATE = { loading: {}, errors: {} };
const photosReducer = (state = INITIAL_STATE, action = {}) => {
switch (action.type) {
case "PHOTOS_FETCH_ERROR":
return {
...state,
error: { ...state.error, photosFetch: action.error },
loading: { ...state.loading, photosFetch: false },
};
// ...
}
};Each error gets its own state value
const photosFetchError = (error) => ({ type: "PHOTOS_FETCH_ERROR", error });
// redux-thunk
const photosFetch = () => (dispatch) => {
dispatch(photosFetchStart());
return fetch("https://some.url")
.then((response) => response.json())
.then((photos) => dispatch(photosFetchSuccess(photos)))
.catch((error) => dispatch(photosFetchError(error)));
};Error message reducer
const errorMessage = (state = null, action) => {
const { type, error } = action
if (type === ActionTypes.RESET_ERROR_MESSAGE) {
return null
} else if (error) {
return error
}
return state
}See more about this in this code snippet
See this lesson from Dan Abramov for more on the topic of error messages in Redux.
Redux blog article - Praise of Redux
I’d compare the difference of a React-Redux app to e.g. a meteor app as comparing elephants (? months of pregnancy + ? years to independence) to birds (? months of pregnancy + ? years to independent life).
If you’re able to build and fully understand a Todo App with React + Redux, you’re up an running to create a fully fleshed production ready web app. If you’re able to write a todo app with meteor, there’s still very much to learn to pull of something more sophisticated although it’s great to get small projects running fast if you need server and client.
Discuss on Twitter ● Improve this article: Edit on GitHub