All notes
Redux

Functions and store

createStore

createStore(reducer, [preloadedState], [enhancer])

reducer (Function): A reducing function that returns the next state tree, given the current state tree and an action to handle.

[preloadedState] (any): The initial state. You may optionally specify it to hydrate the state from the server in universal apps, or to restore a previously serialized user session. If you produced reducer with combineReducers, this must be a plain object with the same shape as the keys passed to it.

[enhancer] (Function): The store enhancer. You may optionally specify it to enhance the store with third-party capabilities such as middleware, time travel, persistence, etc. The only store enhancer that ships with Redux is applyMiddleware().

dispatch



import { createStore } from 'redux'

function todos(state = [], action) {
  switch (action.type) {
    case 'ADD_TODO':
      return state.concat([action.text])
    default:
      return state
  }
}

let store = createStore(todos, ['Use Redux'])

store.dispatch({
  type: 'ADD_TODO',
  text: 'Read the docs'
})

console.log(store.getState())
// [ 'Use Redux', 'Read the docs' ]

getState

getState() Returns the current state tree of your application. It is equal to the last value returned by the store's reducer.

subscribe

subscribe(listener). Adds a change listener. It will be called any time an action is dispatched.

Returns a function that unsubscribes the change listener.

Warning: Calling dispatch() without any conditions is technically possible, however it leads to an infinite loop as every dispatch() call usually triggers the listener again.

It is a low-level API. Most likely, instead of using it directly, you'll use React (or other) bindings.

The Store is also an Observable, so you can subscribe to changes with libraries like RxJS.



function select(state) {
  return state.some.deep.property
}

let currentValue
function handleChange() {
  let previousValue = currentValue
  currentValue = select(store.getState())

  if (previousValue !== currentValue) {
    console.log(
      'Some deep nested property changed from',
      previousValue,
      'to',
      currentValue
    )
  }
}

let unsubscribe = store.subscribe(handleChange)
unsubscribe()

replaceReducer

replaceReducer(nextReducer) Replaces the reducer currently used by the store to calculate the state. It is an advanced API. You might need this if your app implements code splitting, and you want to load some of the reducers dynamically. You might also need this if you implement a hot reloading mechanism for Redux.

store

Never mutate it


Instead of returning Object.assign(state, newData) from your reducers
return Object.assign({}, state, newData). This way you don't override the previous state.

You can also write return { ...state, ...newData } if you enable the "object spread operator" proposal. See the following section.

Object spread operator

github.com: reactjs: using object spread operator.



return Object.assign({}, state, {
        visibilityFilter: action.filter
      })

// Can be converted as:
return { ...state, visibilityFilter: action.filter }

The object spread syntax is still a Stage 3 proposal for ECMAScript. To enable it:


// use your existing es2015 preset
// install babel-plugin-transform-object-rest-spread

// add it individually to the plugins array in your .babelrc.
{
  "presets": ["es2015"],
  "plugins": ["transform-object-rest-spread"]
}

mapStateToProps, mapDispatchToProps and connect

stackOverflow.

In the context of the container-component pattern, your components are supposed to be concerned only with displaying stuff. The only place they are supposed to get information from is their props.

And containers are for:



//---------- Component
class FancyAlerter extends Component {
    sendAlert = () => {
        this.props.sendTheAlert()
    }

    render() {
        <div>
          <h1>Today's Fancy Alert is {this.props.fancyInfo}</h1>
          <Button onClick={sendAlert}/>
        </div>
     }
}

//---------- Container

// Define how you handle events
function mapDispatchToProps(dispatch) {
    return({
        sendTheAlert: () => {dispatch(ALERT_ACTION)}
    })
}

// Define how you get the stuff to display
function mapStateToProps(state} {
    return({fancyInfo: "Fancy this:" + state.currentFunnyString})
}

export const FancyButtonContainer = connect(
    mapStateToProps, mapDispatchToProps)(
    FancyAlerter
)

ownProps


mapStateToProps(state, [ownProps]): stateProps;
mapDispatchToProps(dispatch, [ownProps]): dispatchProps;

stackOverflow: what is the use of the ownProps.

If the ownProps parameter is specified, react-redux will pass the props that were passed to the component into your connect functions. So, if you use a connected component like this:



import ConnectedComponent from './containers/ConnectedComponent'

<ConnectedComponent
  value="example"
/>

// The ownProps inside your mapStateToProps and mapDispatchToProps functions will be an object:
// { value: 'example' }
// And you could use this object to decide what to return from those functions.

Convinience

compose

Composes functions from right to left. github.com.



import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk'
import DevTools from './containers/DevTools'
import reducer from '../reducers'

const store = createStore(
  reducer,
  compose(
    applyMiddleware(thunk),
    DevTools.instrument()
  )
)