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}) => ( )