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

Kenneth Skovhus

April 19, 2016
Tweet

More Decks by Kenneth Skovhus

Other Decks in Programming

Transcript

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

    2007 Offices in Copenhagen, Berlin, Palo Alto ~30 engineers in Copenhagen
  2. 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.
  3. 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)
  4. Presentation Tracking App flow bootstrapping Validation Data model management Data

    syncing + Handlebars templates and styling (both presentation)
  5. 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...
  6. And if it works for Airbnb, BBC, Dropbox, Facebook, Instagram,

    Netflix, Paypal, Podio, Salesforce, Uber, Wordpress, Yahoo...
  7. 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
  8. Process improvements • Less stepping on each others toes •

    Easier to parallelize work • We write more tests (trivial to unit test a component)
  9. 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)
  10. 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
  11. Hello UI Component library const Checkbox = require('ui/checkbox'); <Checkbox/> •

    Abstracts away implementation details • Easier upgrade path when changing UI Components
  12. 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…)
  13. Playing well with other kids backboneCollection.on('sync', (models) => { store.dispatch(actionCreators.sync(models));

    }); backboneCollection.on('destroy', (model) => { store.dispatch(actionCreators.destroy(model)); });
  14. 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
  15. // 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}/>);
  16. 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(); });
  17. 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(); });
  18. 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(); });
  19. 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
  20. Give a small boy a hammer, and he will find

    that everything he encounters needs pounding Law of the instrument
  21. 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
  22. What leaks? • Virtual DOM abstraction ◦ Unsupported node attributes

    (Object, SVG) ◦ React 15 solves this ◦ Will they keep up to date with new DOM features?
  23. 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
  24. Technology lockdown • Can we migrate away from React/Redux? •

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

    on the user and all else will follow