Akiq2016 / blog

notes
4 stars 0 forks source link

redux-learning #21

Open Akiq2016 opened 6 years ago

Akiq2016 commented 6 years ago

tutorial

Actions

Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. You send them to the store using store.dispatch().

interface Action {
  type: string;
  [propName: string]: any; // It'd be better to pass as little data in each action as possible.
}

Action creators are exactly that—functions that create actions. In Redux, action creators simply return an action:

const ADD_TODO = 'ADD_TODO'
function addTodo(text) {
  return {
    type: ADD_TODO,
    text
  }
}

Reducers

Reducers specify how the application's state changes in response to actions sent to the store. Remember that actions only describe the fact that something happened, but don't describe how the application's state changes.

// Reducer is a pure function. What a reducer do:
(previousState, action) => newState

As a pure function, here's are things you should never do inside a reducer:

  1. Mutate its arguments;
  2. Perform side effects like API calls and routing transitions;
  3. Call non-pure functions, e.g. Date.now() or Math.random().

That's said, given the same arguments, it should calculate the next state and return it. No surprises. No side effects. No API calls. No mutations. Just a calculation.

For example:

function todoApp(state = initialState, action) {
  switch (action.type) {
    case SET_VISIBILITY_FILTER:
      return Object.assign({}, state, {
        visibilityFilter: action.filter
      })
    default:
      return state
  }
}
  1. We don't mutate the state. We create a copy with Object.assign(). You can also enable the object spread operator proposal to write { ...state, ...newState } instead.
  2. We return the previous state in the default case. It's important to return the previous state for any unknown action.

while your app grows more complex, you'll want to split your reducing function into separate functions, each managing independent parts of the state. The combineReducers helper function can turn an object whose values are different reducing functions into a single reducing function you can pass to createStore.

Store

You'll only have a single store in a Redux application. The store has the following responsibilities:

  1. Holds application state;
  2. Allows access to state via getState();
  3. Allows state to be updated via dispatch(action);
  4. Registers listeners via subscribe(listener);
  5. Handles unregistering of listeners via the function returned by subscribe(listener).
import { createStore } from 'redux'
import reducers from './reducers'
let store = createStore(reducers)

Demo1

Having the above knowledge, a simple store's update logic can be like this:

import {
  addTodo,
  toggleTodo,
  setVisibilityFilter,
  VisibilityFilters
} from './actions'
 
// Log the initial state
console.log(store.getState())
 
// Every time the state changes, log it
// Note that subscribe() returns a function for unregistering the listener
const unsubscribe = store.subscribe(() =>
  console.log(store.getState())
)
 
// Dispatch some actions
store.dispatch(addTodo('Learn about actions'))
store.dispatch(addTodo('Learn about reducers'))
store.dispatch(addTodo('Learn about store'))
store.dispatch(toggleTodo(0))
store.dispatch(toggleTodo(1))
store.dispatch(setVisibilityFilter(VisibilityFilters.SHOW_COMPLETED))
 
// Stop listening to state updates
unsubscribe()
Akiq2016 commented 6 years ago

Using Redux with other frameworks

For example, React. React bindings for Redux embrace the idea of separating presentational and container components.

-- Presentational Components Container Components
Purpose How things look (markup, styles) How things work (data fetching, state updates)
Aware of Redux No Yes
To read data Read data from props Subscribe to Redux state
To change data Invoke callbacks from props Dispatch Redux actions
Are written By hand Usually generated by React Redux

Most of the components we'll write will be presentational, but we'll need to generate a few container components to connect them to the Redux store. Technically you could write the container components by hand using store.subscribe(). But React Redux makes many performance optimizations that are hard to do by hand. So we'd be better to use the connect() function provided by React Redux.