Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

How to write bad code in redux (ReactNext 2018)

We've been using Redux since it just started, and we learned a lot from dozens of projects, big and small.
This is a taste of a collection of tools and best practices that work great for us.

  • Login to see the comments

  • Be the first to like this

How to write bad code in redux (ReactNext 2018)

  1. 1. How to Write Bad code in Redux Adam Klein
  2. 2. Developer, Consultant, Trainer CEO @ 500Tech Adam Klein
  3. 3. common misconception Redux is a single source of truth
  4. 4. opinionated toolbox and best practices
  5. 5. Immutability
  6. 6. lodash/fp Immutability
  7. 7. lodash/fp Immutability set('inner.property', 'value', state);
  8. 8. lodash/fp Immutability set('inner.property', 'value', state); { ...state, inner: { ...state.inner, property: 'value' } }
  9. 9. lodash/fp Immutability set('inner.property', 'value', state); { ...state, inner: { ...state.inner, property: 'value' } }
  10. 10. const newState = { ...state }; newState.inner.property = 'newValue'; 3rd party libraries <NastyThirdPartyComponent myProp={ myImmutableState }> </NastyThirdPartyComponent> Immutability
  11. 11. Immutability redux-freeze
  12. 12. Immutability use only in development redux-freeze
  13. 13. Immutability ImmutableJS redux-freeze
  14. 14. don’t deep clone the state
  15. 15. ComponentsState
  16. 16. ComponentsState Deep Clone
  17. 17. ComponentsState
  18. 18. ComponentsState Minimal change
  19. 19. Immer const nextState = produce(baseState, draftState => { draftState.push({todo: "Tweet about it"}) draftState[1].done = true }) Immutability
  20. 20. Reducers
  21. 21. Reducers import { handleActions } from 'redux-actions'; const myReducer = handleActions( { [MY_ACTION]: (state: MyState, action: MyAction): MyState => set('key', action.payload, state) }, ... );
  22. 22. Reducers import { handleActions } from 'redux-actions'; const myReducer = handleActions( { [MY_ACTION]: (state: MyState, action: MyAction): MyState => set('key', action.payload, state) }, ... );
  23. 23. Selectors
  24. 24. Reselect Selectors state valueFunctionstate value
  25. 25. Selectors state value access Function state computed value Reselect
  26. 26. Selectors state value access Function state computed value Reselect
  27. 27. Selectors state value access Function state computed value Reselect
  28. 28. // reducer return { products: action.payload, activeProducts: action.payload.filter(...) } Selectors
  29. 29. // reducer return { products: action.payload, activeProducts: action.payload.filter(...) } Selectors
  30. 30. // reducer return { products: action.payload, activeProducts: action.payload.filter(...) } Selectors
  31. 31. const mapStateToProps = (state) => ({ activeProducts: selectActiveProducts(state) }); using a selector Selectors
  32. 32. Selectors - store - reducers - selectors - actions
  33. 33. Selectors posts comments selector reducer reducer - store - reducers - selectors - actions
  34. 34. Side-Effects
  35. 35. Side-Effects Middlewares
  36. 36. Side-Effects Middlewares API Middleware Start Loading End Loading Success ActionFetch Action
  37. 37. Side-Effects Middlewares thunk saga redux-observable
  38. 38. Side-Effects Middlewares thunk saga redux-observable
  39. 39. State Design
  40. 40. State Design
  41. 41. { users: { 1: { id: 1, name: 'User1' }, 2: { id: 2, name: 'User2' } }, selectedUserIds: { 1: true } } State Design
  42. 42. { users: { 1: { id: 1, name: 'User1' }, 2: { id: 2, name: 'User2' } }, selectedUserIds: { 1: true } } State Design
  43. 43. { users: { 1: { id: 1, name: 'User1' }, 2: { id: 2, name: 'User2' } }, selectedUserIds: { 1: true } } Reload server data State Design
  44. 44. { users: { 1: { id: 1, name: 'User1' }, 2: { id: 2, name: 'User2' } }, selectedUserIds: { 1: true } } Save & restore from
 Localstorage State Design
  45. 45. Code Reuse
  46. 46. User Reducer: user: { isLoading: true, data: {...} } jobs: { isLoading: true, data: {...} } Jobs Reducer: etc. Code Reuse
  47. 47. User Reducer: user: { isLoading: true, data: {...} } jobs: { isLoading: true, data: {...} } Jobs Reducer: etc. Code Reuse
  48. 48. User Reducer: user: { isLoading: true, data: {...} } jobs: { isLoading: true, data: {...} } Jobs Reducer: etc. Code Reuse
  49. 49. const START_LOADING = 'START_LOADING'; const END_LOADING = 'END_LOADING'; pendingRequests: { user: 1, jobs: 0 } network actions network reducer Code Reuse
  50. 50. pendingRequests: { user: 1, jobs: 0 } Code Reuse
  51. 51. pendingRequests: { user: 1, jobs: 0 } Code Reuse user: { pendingRequests: 1 }, jobs: { pendingRequests: 0 }
  52. 52. pendingRequests: { user: 1, jobs: 0 } Code Reuse user: { pendingRequests: 1 }, jobs: { pendingRequests: 0 }
  53. 53. next(action); dispatch(startLoading(action.payload.label)); makeRequest(...) .then(() => dispatch(endLoading(action.payload.label))) .catch(() => dispatch(endLoading(action.payload.label))); API middleware Code Reuse
  54. 54. next(action); dispatch(startLoading(action.payload.label)); makeRequest(...) .then(() => dispatch(endLoading(action.payload.label))) .catch(() => dispatch(endLoading(action.payload.label))); API middleware FETCH_USER log Code Reuse
  55. 55. next(action); dispatch(startLoading(action.payload.label)); makeRequest(...) .then(() => dispatch(endLoading(action.payload.label))) .catch(() => dispatch(endLoading(action.payload.label))); FETCH_USER START_LOADING (‘user’) log Code Reuse API middleware
  56. 56. next(action); dispatch(startLoading(action.payload.label)); makeRequest(...) .then(() => dispatch(endLoading(action.payload.label))) .catch(() => dispatch(endLoading(action.payload.label))); FETCH_USER START_LOADING (‘user’) END_LOADING (‘user’) log Code Reuse API middleware
  57. 57. next(action); dispatch(startLoading(action.payload.label)); makeRequest(...) .then(() => dispatch(endLoading(action.payload.label))) .catch(() => dispatch(endLoading(action.payload.label))); FETCH_USER START_LOADING (‘user’) END_LOADING (‘user’) log Code Reuse API middleware
  58. 58. const reducer = compose( withLoading withSelection withTags, withPermissions )(usersReducer) Higher-order reducers Code Reuse
  59. 59. Our boilerplate https://bitbucket.org/500tech/react-redux-project-boilerplate
  60. 60. Redux Masterclass https://www.meetup.com/React-il
  61. 61. Time for Questions

×