Redux

  • one state for all
  • data and ui state in single object: state or state tree
  • state tree: readonly
  • action needs to have type propery (can be non-string)

episode 5

  • initial state: typeof state === 'undefined' => return default state
  • defaults in method params also works
  • arrow function: clearer semantics in es6?!?

episode 6

  • umd build: single global variable
  • npm bundler and webpack or browserfy in real apps

episode 7

const createStore = (reducer) => {
    let state
    const getState = () => state;
    const dispatch = (action) => {}
    return { getState, dispatch }
}

* always use !== and ===

episode 8

    const Counter = ({value, onIncrement, onDecrement}) => {
        // do something
    }

episode 9

  • deep-freeze: code is free of mutations

    const f = [] deepFreeze(f) f.push(1) // should break

    [].concat(1) => [1] […list, 1]

    let a = [1, 2, 3] expect([…a, 4]).toEqual([1, 2, 3, 4])

    [].splice mutates arrays! [].slice does not but you need to combine

    […list.slice(0, index),list[index]+1,…list.slice(index + 1)]

  • either concat and spread operator, protect with deep-freeze

episode 10

  • expect: create separate test files and always expect(funCall(before)).toEqual(after) with constants
  • Object.assign({}, { a: 1, b: 2 }, {a: 2})
  • Object.assign does not work well in typescript (without polyfill): see https://github.com/Microsoft/TypeScript/issues/3429
  • object spread works in both: {…todos, x: 2, z: 3}
  • object spread in babel via stage2 (or stage-2) preset

episode 11

  • any reducer has to return the current state fo runknown actions
  • action: type: “ADD_TODO”

episode 12

  • action: type: “TOGGLE_TODO”
  • changing single items can be done via state.map and checking the index value (and the copy the value)

    return state.map(todo => { if todo.id !=== action.id { return todo } return {…todo, completed: !todo.completed} })

episode 13

  • extract todo reducer from todos reducer with same actions
  • reducer composition: reducers on parts of state tree, delegate reducers to other reducers (recursive)

episode 14

  • reducer composition pattern
  • reducer which passes different paths of the state to separate reducers

episode 15

  • combineReducers: convenience for reducer composition pattern
  • name reducers after state parts and combine with {todos,visibilityFilter}

episode 16

  • Object.keys({a: 1, b: 2})
  • expect([1, 2, 3].reduce((a, b) => { return a + b })).toEqual(6)

episode 17

<input ref={node => {
    this.input = node
}} />
<button onClick={() => {
    console.log(this.input.value);
})

episode 18

textDecoration: todo.completed ? 'line-through' : 'none'

episode 19

<a href="#" onClick={e => e.preventDefault()}>link</a>

episode 20

  • presentational components: no logic, only know how to render
  • separate props instead of nested model

episode 21

  • separate looks and behavior
  • component needs to have a single root element
  • local variables suitable for keeping state

    const AddTodo = ({onAddClick}) => {
        let input;
        return <div>
            <input ref={node => {
                input = node;
            } />
            <button onClick={() => {
                onAddClick(input.value)
                input.value = ''
            }}Click me </button>
        </div>
    }
    
  • prefer function over component classes

  • function names: onClick, onAddClick, onFilterClick, etc…

  • spread operator for nested components

    <Todo key={todo.id} {...todo} onClick={() => console.log("clicked"} />
    
  • whitespace via

    Show
    {' '}
    <a href="">Link</a>
    
  • container component specify behavior

episode 22

  • container components sit between presentational components and get state from redux
  • subscribe to redux store in e.g. componentDidMount, calling this.forceUpdate()
  • subscriptions in componentDidMount need to be unsubscribed in componentWillUnmount
  • store.subscribe() returns unsubscribe functiuon
  • container: data and behavior

episode 23

  • container component names: TodoList => VisibleTodoList
  • container component: connect presentational components to redux store and specify state and behavior they need
  • container components subscribe to redux store
  • sometimes it is better to keep props and behavior together
  • only separate container and presentational components when it reduces complexity of codebase
  • extract presentational components first and only introduce container components when one needs to pass too much boilerplate around

episode 24

  • perfectly fine to read state from store in render function of container components (assign it to const state = store.getState()
  • passing store via props instead of using a global store (but not practical)

episode 25

  • react context
  • getChildContext will be called by react and provide that context to all children
  • Provider.childContextTypes = { store: react.PropTypes.object } must be defined, define which contexts to receive
  • this.context then holds the store
  • context as a wormhole
  • context is second argument to functional components

episode 26

  • react-redux contains Provider component const { Provider } = ReactRedux

    import { Provider } from ‘react-redux’ var Provider = require(‘react-redux’).Provider

episode 27

  • mapStateToProps and mapDispatchToProps are merged into final props
  • connect makes container components out of presentatinal components

episode 28

  • every component should be in a separate file and so we can always use mapStateToProps and mapDispatchToProps
  • context is unstable API
  • we can also always just pass the dispatch function itself
  • using let Component ... allows us redefining the Component via connect without need for an extra name
  • providing null as props tells connect that there is no need to subscribe to the store
  • providing null as the second argument automatically injects dispatch as a prop
  • connect without arguments does not subscribe to store and injects the dispatch component in the props

episode 29

  • props are passed to mapStateToProps as second argument
  • props is also the second argument to mapDispatchToProps
  • use ownProps to avoid conflicts with props

episode 30

  • extracting action creators is a common pattern in react apps
  • action creators document your software, they show which actions the components can dispatch

Part II

episode 1

  • if arrow function only contains a single return statement we can replace the statement with just that value

episode 2

  • initial state can be passed as second argument to createStore function, handled via a specific action

episode 3

  • localStorage.getItem(‘item’)
  • localStorage.setItem(‘item’, state)
  • always use try catch around localStorage actions
  • visible state is normally not stored in localStorage
  • yarm add node-uuid => require(“node-uuid”).v4()
  • yarn lodash => allow throtteling of specific functions
  • import throttle from ‘lodash/throttle’

episode 5

import { Router, Route, browserHistory } from ‘react-router’

episode 6

<Link activeStyle={{textDecoration: 'none'}}>current</Link> to style current links

episode 7

  • react router passes params prop to mounted components

    const App = ({params}) => ( )

continue: https://egghead.io/lessons/javascript-redux-using-withrouter-to-inject-the-params-into-connected-components