Redux in Action
Part Two: Scable Redux Application
- Framework intuitive space
The space the framework was built to solve
- Framework negative space
The space that framework doesn't solve or have an opinion on
“Don’t fall into the trap of thinking a library should prescribe how to do everything.”
“The perfect is the enemy of the good.”
Splitting Up Reducer
- Store
- Action
- Reducer
store
action
reducer
Splitting Up Reducer


One Fat Reducer VS. Splitted Thin Reducers

Splitting Up Reducer
Problems & Solutions:
- Separating Data Handling by Domain
- Combining Reducers by Slice with combineReducers
- Sharing data between slice reducers
- Boilerplate code
Get necessary data in action creators, and pass the data through actions.
Use high order functions to generate reducers.
- Using slice reducers with ImmutableJS
Normalizing State Shape

Duplicated and Nested Structure
- Updating a piece of duplicated data is difficult
- Reducer logic in a deep nested state tree is complicated
- Performance issues
Data Normalizing

Using 'byId and allIds' Pattern
- Use 'byId' to store entities
- Use 'allIds' to indicate ordering
Data Normalizing
Using ImmutableJS Record to Validate Entity Shape

- Entities becomes self-documenting
- Only the fileds in the record defination can be set
Data Normalizing
- Each type of data gets its own "table" in the state.
- Each "data table" should store the individual items in an object, with the IDs of the items as keys and the items themselves as the values.
- Any references to individual items should be done by storing the item's ID.
- Arrays of IDs should be used to indicate ordering.
Data Normalizing
Problems & Solutions:
- More components are connected and each component is responsible for looking up its own data
- State need to be computed rather get from the store directly
Use selectors to encapsulate the state shape and make the selecting reuseable.
Simply pass item IDs to connected children is a good pattern for optimizing UI performance
ImmutableJS
Pros:
Cons:
- Guaranteed immutability
- Rich API
- Performance
- Difficult to interoperate with
- Once used, Immutable.JS will spread throughout your codebase
- Difficult to debug
ImmutableJS
- Never mix plain JavaScript objects with ImmutableJS
- Make your entire Redux state tree an ImmutableJS object
- Limit your use of toJS()
- Never use toJS() in mapStateToProps()
- Your selectors should return ImmutableJS objects
- Use ImmutableJS objects in your connected components
Selectors
Encapsulating the Redux State Tree
- Wrting
- Reading
Reducers、action creators encapsulate the writing to the redux state tree.
Reading from the redux state tree is scattered through mapStateToProps(), action creators, sagas and tests. It's hard to update the state shape.
Use selectors to encapsulate the reading from the redux state tree.
store
reducer
Redux
state
action
UI
DOM Event
Network
……
Selectors
Reading state
Reading state
Selectors
state.todos
selectAllTodos(state)
state.todos.filter((todo) => !todo.complete).length
selectActiveTodosCount(state)
Selectors
Using Reselect to Compose Selectors and Memorize the Results

Data caching
- 'getSomethingIfNeeded' Pattern
- Using memorized api request
Naming action creators, thunks or sagas with 'getSomethingIfNeeded' pattern

Business Logic
- Components
- Action Creators(Redux-Thunk)
- Reducers
- Sagas
- validation, verification, authorization
- transformation, augmentation, applying defaults
- processing — asynchronous things
Where to put business logic
×
×
√
√
Business Logic
Commands and Events
- LOAD_USER is a command
- USER_LOADED is a event
Commands:
- What to do
- Expected result
- Only one specified receiver
Events:
- What happened
- No expected result
- Don't care about receivers
- Immutable
Business Logic
- Components
Where to put business logic
×
- Keep components as pure as possible
- Components are responsible for presentation
- Components publishes events to trigger business logic
- Not for resuablity, but for simplicity - easy to modify and debug
Business Logic
- Reducers
Where to put business logic
×
- Reducers need to be pure (synchronous、no side effects)
- Reducers are responsible for state updating
Business Logic
- Action Creators(Redux-Thunk)
Where to put business logic
- What is a thunk
√


Business Logic
- Action Creators(Redux-Thunk)
Where to put business logic
- Access global state esaily
- Not easy to control complicated async flow
- Simple and focused
√
Business Logic
- Sagas
Where to put business logic
√
A saga is
- A piece of code which runs in the background
- Watching for dispatched actions
- May perform some async calls (or synchronous impure calls like browser storage) and can dispatch other actions to the store.
Business Logic
- Sagas
Where to put business logic
√
- Components do not perform any business logic but only dispatch actions to notify what happened
- A saga can also act as a decoupling point between 2 parts of the UI
Business Logic
store
reducer
Redux
state
action
UI
DOM Event
Network
……
Business Logic
store
reducer
Redux
state
action
UI
DOM Event
Network
……
action
Saga
Business Logic
Saga
Worker1
Worker2
Worker3
action
action
Task
Result
Task
Result
Task
Result
Business Logic
Generator and Runner

Redux in Action - Scable Redux Application
By yiliang_wang
Redux in Action - Scable Redux Application
- 178