Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Evaluating a year working with React & Redux

Evaluating a year working with React & Redux

Talk given at "React and Redux Copenhagen" meetup. http://www.meetup.com/React-and-Redux-Copenhagen/events/230043991

Although we were early adopters of Redux, "evaluating a year working with React & Redux" is bit of a stretch. It was introduced at React Europe 2015 in June...

https://twitter.com/kenneth_skovhus

6923aa25bf3f00c27df529c4419daf94?s=128

Kenneth Skovhus

April 19, 2016
Tweet

Transcript

  1. Evaluating a year working with React & Redux @kenneth_skovhus React

    and Redux Copenhagen April 19, 2016
  2. Hi! Kenneth Skovhus Full stack software engineer at issuu React/Redux

    believer
  3. issuu is like YouTube for publications

  4. 25+ million publications 100 million unique visitors/mo Founded in Copenhagen

    2007 Offices in Copenhagen, Berlin, Palo Alto ~30 engineers in Copenhagen
  5. None
  6. Why are all we here?

  7. Building rich client-side web applications (in React/Redux)

  8. React View library by Facebook providing a high level abstraction

    for rendering user interfaces and neat way to create components. V in MV* Flux Fancy term for front-end app architecture based on unidirectional data flow. Provides simple mental model of the application. Redux Becoming the de facto flux implementation.
  9. None
  10. HOT AIR?

  11. Where did we come from?

  12. Client side eras at issuu.com The golden Macromedia Flash days

    (2007) Vanilla JS + jQuery (2009) Frameworks! Ember 1.0.0-rc.* (2013) Libraries! Backbone MV* + Handlebars (2014)
  13. And they all ended up looking like...

  14. Presentation Tracking App flow bootstrapping Validation Data model management Data

    syncing + Handlebars templates and styling (both presentation)
  15. None
  16. Why is building client side applications difficult? Unstable requirements Design

    and UX adjustments Unlimited number of valid solutions Front-end novelties at crazy pace JavaScript...
  17. Why did we settle on React/Redux?

  18. We believed in Declarative UIs Composable components Unidirectional data flow

    Libraries instead of frameworks
  19. And if it works for Airbnb, BBC, Dropbox, Facebook, Instagram,

    Netflix, Paypal, Podio, Salesforce, Uber, Wordpress, Yahoo...
  20. Where are we using React/Redux?

  21. Document reader (high traffic/usage)

  22. Publisher Landing Page (dashboard)

  23. Publisher Tools (create, read, update, delete)

  24. Embed widget (form heavy)

  25. InDesign plugin

  26. None
  27. React/Redux findings & recommendations

  28. Quick adaption of React • Small slowdown for first project

    • Fairly short learning curve • Great documentation to get started • People still enjoys the new paradigm & DX • Designers feels at home in JSX
  29. Process improvements • Less stepping on each others toes •

    Easier to parallelize work
  30. Process improvements • Less stepping on each others toes •

    Easier to parallelize work • We write more tests (trivial to unit test a component)
  31. Process improvements • Less stepping on each others toes •

    Easier to parallelize work • We write more tests (trivial to unit test a component) • Refactoring rather easy (always write PropTypes)
  32. Structuring your application • Presentational Components (view) ◦ Are only

    concerned with how things look ◦ Pure function, no dependency on actions/store • Containers (controller-views) ◦ Provide data to components or other containers ◦ Stateful, connects application to actions, store https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0
  33. Goodbye copy-paste markup <label class="ui-checkbox"> <input checked type="checkbox" class="ui-checkbox__native" />

    <div class="ui-checkbox__faux"></div> </label>
  34. Hello UI Component library const Checkbox = require('ui/checkbox'); <Checkbox/>

  35. Hello UI Component library const Checkbox = require('ui/checkbox'); <Checkbox/> •

    Abstracts away implementation details • Easier upgrade path when changing UI Components
  36. Playing well with other kids • Revamping UI of older

    Backbone application • We wanted to replace the Backbone/Handlebars view layer with React • Keep complex old Backbone Models and Collections intact (if it ain’t broken…)
  37. Playing well with other kids backboneCollection.on('sync', (models) => { store.dispatch(actionCreators.sync(models));

    }); backboneCollection.on('destroy', (model) => { store.dispatch(actionCreators.destroy(model)); });
  38. Cosmos (Component Playground) • Work on presentational components in isolation

    • Fixtures to bootstrap your initial state • Document what state a component can be in • Great developer experience for building components • Improves workflow with designers (~ InVision) github.com/skidding/cosmos
  39. github.com/skidding/cosmos

  40. Idea: Using fixtures to test rendering Simply render all presentational

    components with their Playground fixtures.
  41. // Find all presentational components const components = glob.sync('./components/**/*.@(js|jsx)'); //

    Find all fixtures for a given component by doing some more globbing const componentFixture = getFixturesForComponent(c); test('Renders component with fixture data', t => { const oldError = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(<componentFixture.Component {... fixture.content}/>);
  42. test('Renders component with fixture data', t => { const oldError

    = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(<componentFixture.Component {... fixture.content}/>); t.pass(`Rendering ${componentFixture.name} (${fixture.name})`); } catch (e) { t.fail(`Failed rendering ${componentFixture.name} (${fixture.name})`); } }); console.error = oldError; t.end(); });
  43. test('Renders component with fixture data', t => { const oldError

    = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(<componentFixture.Component {... fixture.content}/>); t.pass(`Rendering ${componentFixture.name} (${fixture.name})`); } catch (e) { t.fail(`Failed rendering ${componentFixture.name} (${fixture.name})`); } }); console.error = oldError; t.end(); });
  44. test('Renders component with fixture data', t => { const oldError

    = console.error; console.error = function(warning) { if (/(Invalid prop|Failed propType)/.test(warning)) { t.fail(`Failed rendering ${currentComponent}: ${warning}`); } oldError.apply(console, arguments); }; componentFixture.fixtures.forEach(fixture => { try { renderToString(<componentFixture.Component {... fixture.content}/>); t.pass(`Rendering ${componentFixture.name} (${fixture.name})`); } catch (e) { t.fail(`Failed rendering ${componentFixture.name} (${fixture.name})`); } }); console.error = oldError; t.end(); });
  45. Idea: Using fixtures to test rendering Simply render all presentational

    components with their Playground fixtures. • Forces you to document/write fixtures • Asserts no runtime errors or missing props for all meaningful states without much effort
  46. None
  47. All good?

  48. Give a small boy a hammer, and he will find

    that everything he encounters needs pounding Law of the instrument
  49. As a result of the great DX, developers thinks: “React

    is the hammer that makes all problems look like a nail” May lead to over-engineering
  50. None
  51. Leaky Abstractions

  52. None
  53. What leaks? • Virtual DOM abstraction ◦ Unsupported node attributes

    (Object, SVG) ◦ React 15 solves this ◦ Will they keep up to date with new DOM features?
  54. What leaks? • Virtual DOM abstraction ◦ Unsupported node attributes

    (Object, SVG) ◦ React 15 solves this ◦ Will they keep up to date with new DOM features? • Animations still feels cumbersome • Combined with Redux you lose Inversion of Control
  55. Technology lockdown • Can we migrate away from React/Redux?

  56. Technology lockdown • Can we migrate away from React/Redux? •

    Do I believe in: ◦ Declarative UIs ◦ Composable components ◦ Unidirectional data flow
  57. None
  58. Focus on the user and all else will follow Focus

    on the user and all else will follow
  59. None
  60. @kenneth_skovhus React and Redux Copenhagen April 19, 2016 Questions?

  61. @kenneth_skovhus React and Redux Copenhagen April 19, 2016 Thanks