Redux in Russian
  • Read Me
  • Introduction
    • Motivation
    • Core Concepts
    • Three Principles
    • Prior Art
    • Learning Resources
    • Ecosystem
    • Examples
  • Basics
    • Actions
    • Reducers
    • Store
    • Data Flow
    • Usage with React
    • Example: Todo List
  • Advanced
    • Async Actions
    • Async Flow
    • Middleware
    • Usage with React Router
    • Example: Reddit API
    • Next Steps
  • Recipes
    • Configuring Your Store
    • Migrating to Redux
    • Using Object Spread Operator
    • Reducing Boilerplate
    • Server Rendering
    • Writing Tests
    • Computing Derived Data
    • Implementing Undo History
    • Isolating Subapps
    • Structuring Reducers
      • Prerequisite Concepts
      • Basic Reducer Structure
      • Splitting Reducer Logic
      • Refactoring Reducers Example
      • Using combineReducers
      • Beyond combineReducers
      • Normalizing State Shape
      • Updating Normalized Data
      • Reusing Reducer Logic
      • Immutable Update Patterns
      • Initializing State
    • Using Immutable.JS with Redux
  • FAQ
    • General
    • Reducers
    • Organizing State
    • Store Setup
    • Actions
    • Immutable Data
    • Code Structure
    • Performance
    • Design Decisions
    • React Redux
    • Miscellaneous
  • Troubleshooting
  • Glossary
  • API Reference
    • createStore
    • Store
    • combineReducers
    • applyMiddleware
    • bindActionCreators
    • compose
  • Change Log
  • Patrons
  • Feedback
Powered by GitBook
On this page
  • Single source of truth
  • State is read-only
  • Changes are made with pure functions
  1. Introduction

Three Principles

PreviousCore ConceptsNextPrior Art

Last updated 6 years ago

Redux can be described in three fundamental principles:

Single source of truth

The of your whole application is stored in an object tree within a single .

This makes it easy to create universal apps, as the state from your server can be serialized and hydrated into the client with no extra coding effort. A single state tree also makes it easier to debug or inspect an application; it also enables you to persist your app's state in development, for a faster development cycle. Some functionality which has been traditionally difficult to implement - Undo/Redo, for example - can suddenly become trivial to implement, if all of your state is stored in a single tree.

console.log(store.getState())

/* Prints
{
  visibilityFilter: 'SHOW_ALL',
  todos: [
    {
      text: 'Consider using Redux',
      completed: true,
    },
    {
      text: 'Keep all state in a single tree',
      completed: false
    }
  ]
}
*/

State is read-only

This ensures that neither the views nor the network callbacks will ever write directly to the state. Instead, they express an intent to transform the state. Because all changes are centralized and happen one by one in a strict order, there are no subtle race conditions to watch out for. As actions are just plain objects, they can be logged, serialized, stored, and later replayed for debugging or testing purposes.

store.dispatch({
  type: 'COMPLETE_TODO',
  index: 1
})

store.dispatch({
  type: 'SET_VISIBILITY_FILTER',
  filter: 'SHOW_COMPLETED'
})

Changes are made with pure functions

Reducers are just pure functions that take the previous state and an action, and return the next state. Remember to return new state objects, instead of mutating the previous state. You can start with a single reducer, and as your app grows, split it off into smaller reducers that manage specific parts of the state tree. Because reducers are just functions, you can control the order in which they are called, pass additional data, or even make reusable reducers for common tasks such as pagination.

function visibilityFilter(state = 'SHOW_ALL', action) {
  switch (action.type) {
    case 'SET_VISIBILITY_FILTER':
      return action.filter
    default:
      return state
  }
}

function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return [
        ...state,
        {
          text: action.text,
          completed: false
        }
      ]
    case 'COMPLETE_TODO':
      return state.map((todo, index) => {
        if (index === action.index) {
          return Object.assign({}, todo, {
            completed: true
          })
        }
        return todo
      })
    default:
      return state
  }
}

import { combineReducers, createStore } from 'redux'
const reducer = combineReducers({ visibilityFilter, todos })
const store = createStore(reducer)

That's it! Now you know what Redux is all about.

The only way to change the state is to emit an , an object describing what happened.

To specify how the state tree is transformed by actions, you write pure .

state
store
action
reducers