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

Front End Orlando - Introduction to React.js (2...

Front End Orlando - Introduction to React.js (2015-03-31)

A basic introduction to React.js, Jest, and Flux.

James Burnett

March 31, 2015
Tweet

Other Decks in Technology

Transcript

  1. Senior  SoEware  Engineer  @  Tribune  Publishing     Full  Stack

     Engineer   Ruby  on  Rails   React.js   About  Me   Small  Apps   Tribune  Website  Redevelopment   Backend  Content  Management  System  Redesign  
  2. Overview   •  What  is  React.js   •  Building  something

      •  Tes0ng  something   •  Unidirec0onal  Data  Flows  (and  Flux)   •  React  Na0ve  
  3.  components        composed  into  an  app    

             then  re-­‐rendered  on  every  update  
  4. user  interface  is  hard   because   there  is  so

     much  state   UI  elements   design  itera0ons   crazy  environments   mutable  DOM   user  input   anima0on   lots  of  engineers   ajax  calls  
  5. “Our  intellectual  powers  are  rather  geared  to  master   sta0c

     rela0ons  and  our  powers  to  visualize  processes   evolving  in  0me  are  rela0vely  poorly  developed.  For   that  reason  we  should  do  (as  wise  programmers   aware  of  our  limita0ons)  our  utmost  to  shorten  the   conceptual  gap  between  the  sta0c  program  and  the   dynamic  process,  to  make  the  correspondence   between  the  program  (spread  out  in  text  space)  and   the  process  (spread  out  in  0me)  as  trivial  as  possible”     -­‐  Dijkstra  
  6. we  have  libraries   like  backbone,  angular,  and  ember  

    that  try  to  deal  with  the  changing  state  
  7. react  solves  this  by      re-­‐rendering   the  whole

     app                        on  every  change  
  8. re-­‐rendering  makes  things  simple   displayed  data  is  up-­‐to-­‐date  

    no  magical  data  binding   no  model  dirty  checking  
  9. re-­‐rendering  makes  things  simple   displayed  data  is  up-­‐to-­‐date  

    no  magical  data  binding   no  model  dirty  checking   no  more  explicit  DOM  opera0ons  
  10. No,  not  this  guy!   The  Flash  is  that  brief

     flicker  you  get  when  you  re-­‐render  the  DOM    
  11. render  virtual   DOM   diff   batch  change  

    DOM   update   React  Lifecycle   start  
  12. “Some  of  this  stuff  flies  in  the  face  of  best

      prac0ces,  but  these  are  prac0ces  that  deserve   to  be  challenged.”   -­‐  Pete  Hunt  
  13. Components   •  Are   – idempotent   – reusable   – composable

      – testable   •  Combine  DOM  genera0on  and  display  logic  
  14. Example  Component       var  ExampleComponent  =  React.createClass({  

       render:  function()  {          return  <h1>An  Example  Component</h1>;      }   });    
  15. Wait,  are  we  really  going  to  comingle   markup  with

     JavaScript?!?!?!   What  about  Separa0on  of  Concerns?   JSX  
  16. What  is  the  goal  of  Separa0on  of  Concerns    

    High  Cohesion,  Loose  Coupling  
  17. Cohesion  is:   “The  degree  to  which  elements  of  

    a  module  belong  together.”   [Wikipedia](h?p://en.wikipedia.org/wiki/Cohesion_%28computer_science%29)   Quo$ng  Yourdon  &  Constan$ne’s  Structured  Design  book  from  1979  
  18. Coupling  is:   “[the]  degree  of  interdependence   between  soEware

     modules”   [Wikipedia](h?p://en.wikipedia.org/wiki/Coupling_(computer_programming)  
  19. Keeping  view  logic  and  markup  separate  is   not  separa0on

     of  concerns   it  is  really  just  a   separa0on  of  technologies  
  20. components  are              arranged  in

     a  tree      rendered  based  on     props          state  
  21. React  Best  Prac0ces  101   state  is  only  set  on

     the  root  component   parents  pass  props  to  children  
  22. Create  the  Component  Class         Demo1  =

     React.createClass({      displayName:  “Demo1”   });  
  23. Start  with  Render   render:  function()  {      return

     (          <div>              <button  onClick={this.minus}>-­‐</button>              {this.state.value}              <button  onClick={this.plus}>+</button>          </div>      );   }  
  24. JSX  Conversion     <button  onClick={this.minus}>-­‐</button>     becomes  

      React.createElement(      "button",      //  component       )    
  25. JSX  Conversion     <button  onClick={this.minus}>-­‐</button>     becomes  

      React.createElement(      "button",      //  component      {  onClick:  this.minus  },  //  props     )    
  26. JSX  Conversion     <button  onClick={this.minus}>-­‐</button>     becomes  

      React.createElement(      "button",      //  component      {  onClick:  this.minus  },  //  props      "-­‐"          //  children   )    
  27. Ini0al  State   //  because  we  used  {this.state.value}    

    getInitialState:  function()  {      return  {          value:  0      };   }  
  28. Event  Handlers     plus:  function()  {      this.setState({

     value:  this.state.value  +  1  });   }     minus:  function()  {    this.setState({  value:  this.state.value  -­‐  1  });   }    
  29. Add  to  the  DOM   <div  id="app"></div>     <script

     src="http://fb.me/react-­‐0.12.2.js">          </script>   <script  src="http://fb.me/JSXTransformer-­‐0.12.2.js">          </script>     <!-­‐-­‐  React.renderComponent();  -­‐-­‐>  
  30. Add  to  the  DOM   <script  type="text/jsx">      var

     Demo1  =  React.createClass({  ...  });        React.renderComponent(          <Demo1  />,          document.getElementById('app')      );   </script>  
  31. there  are  tools  to  help   browserify   webpack  

    react-­‐rails   browserify-­‐rails  
  32. for  a  good  tutorial  on  geqng  react  setup   (with

     Rails)   https://reactjsnews.com/setting-­‐up-­‐rails-­‐for-­‐react-­‐and-­‐jest/   warning:  shameless  plug  
  33. Smile.jsx     var  React  =  require('react');     var

     Smile  =  React.createClass({  .  .  .  });     module.exports  =  Smile;    
  34. Using  That  Component       var  Smile  =  require('./Smile');

        React.renderComponent(      <Smile  />,      document.getElementById('app')   );    
  35. Jest  is  based  on  Jasmine   it(“should  do  something”,  function()

     {});   describe(“a  group  of  tests”,  function()  {});   beforeEach(function()  {});   expect([condition]).toBe([something])  
  36.    and  it  runs            

             from  the  command  line        in  parallel                            via  node.js   npm  test  [optional  pattern]  
  37. Demo1-­‐test.jsx     jest.dontMock('../Demo1');     describe("Demo1",  function()  {  

       var  React  =  require('react/addons')          ,  TestUtils  =  React.addons.TestUtils          ,  Demo1  =  require('../Demo1')     //  .  .  .     }  
  38. Demo1-­‐test.jsx       it("should  default  to  0  with  buttons

     for  +/-­‐",      function()  {          var  demo1  =  TestUtils      .renderIntoDocument(<Demo1  />);          expect(demo1.getDOMNode().textContent)      .toBe('-­‐0+');      }   );  
  39. Demo1-­‐test.jsx   it("should  increment  the  counter  when      

       clicking  on  the  +  button",  function()  {      var  demo1  =  TestUtils      .renderIntoDocument(<Demo1  />);      var  plusButton  =  TestUtils    .scryRenderedDOMComponentsWithTag(demo1,  'button’)    .filter(function(component)  {  return        component.getDOMNode().textContent  ===  '+’    })[0];          TestUtils.Simulate.click(plusButton)          expect(demo1.getDOMNode().textContent).toBe('-­‐1+');   });  
  40. Jest  API   http://facebook.github.io/jest/docs/api.html#content   dontMock  genMockFunc0on  it/it.only   .not

     .toBe/.toEqual        .toBeDefined        .toBeCalled[With]     React  TestU0ls  API   http://facebook.github.io/react/docs/test-­‐utils.html   renderIntoDocument   Simulate.[event]   [scry/find]RenderedDOMComponentWith[Class/Tag/Type]  
  41. Mocha   http://mochajs.org/   be?er  repor0ng   fewer  issues  with

     auto-­‐mocking   serial  execu0on     Expect.js   https://github.com/Automattic/expect.js   expect,  to.be  
  42. Rethinking  Demo12     propTypes:  {    value:  React.PropTypes.number  

    },     getDefaultProps:  function()  {      return  {  value:  0  };   },  
  43. No  more  state    render:  function()  {      

       return  (              <div>                  <button  onClick={this.minus}>-­‐</button>                  {this.state  props.value}                  <button  onClick={this.plus}>+</button>              </div>          );      }  
  44.  Yay!.  .  .  wait.  .  .        

     it  is  not  doing  anything  anymore  
  45. Parent  Component     onChange:  function(newValue)  {      

       this.setState({  value:  newValue  });   }   render:  function()  {      return  (          <Demo2              value={this.state.value}              onChange={this.onChange}  />      );   }  
  46. The  Case  For  Flux       “your  data  changes

     over  0me”  and  you  “care   about  immediately  reflec0ng  those  changes  in   the  UI”   h?ps://medium.com/@dan_abramov/the-­‐case-­‐for-­‐flux-­‐379b7d1982c6  
  47. The  Case  For  Flux         “you  want

     to  cache  data  in  memory,  but  it  can   change  while  cached”   h?ps://medium.com/@dan_abramov/the-­‐case-­‐for-­‐flux-­‐379b7d1982c6  
  48. The  Case  For  Flux         “your  data

     is  rela0onal  and  models  include  and   depend  on  each  other”     h?ps://medium.com/@dan_abramov/the-­‐case-­‐for-­‐flux-­‐379b7d1982c6  
  49. The  Case  For  Flux         “the  same

     data  is  assembled  from  different   sources  and  can  be  rendered  in  several  places   throughout  the  UI”   h?ps://medium.com/@dan_abramov/the-­‐case-­‐for-­‐flux-­‐379b7d1982c6  
  50. Store   View   Dispatcher   Ac0on   Unidirec0onal  Data

     Flow  (Flux)   ex.  fetch   the  user   model  
  51. Store   View   Dispatcher   Ac0on   Unidirec0onal  Data

     Flow  (Flux)   This  is   where  data   should  be   fetched  
  52. Store   View   Dispatcher   Ac0on   Unidirec0onal  Data

     Flow  (Flux)   This  is  like  the   model.   users:  [      55586:          {someData}   ]  
  53. Store   View   Dispatcher   Ac0on   Unidirec0onal  Data

     Flow  (Flux)   Changes  to   the  store   trigger  a   re-­‐render  
  54. Ac0on   Store   View   Dispatcher   Ac0on  

    Unidirec0onal  Data  Flow  (Flux)   Views  trigger   ac0ons  
  55. Ac0on   Store   View   Dispatcher   Ac0on  

    Unidirec0onal  Data  Flow  (Flux)   And  the  cycle   starts  all  over   again  
  56. Flux  Implementa0ons   •  [Reflux](h?ps://github.com/spoike/refluxjs)   •  [Fluxxor](h?p://fluxxor.com/)   • 

    [Fluxify](h?ps://github.com/arqex/fluxify)   •  [Ambidex]   (h?ps://github.com/appsforar0sts/ambidex)   uses  reflux  
  57. Objec0ves   •  Learn  the  basics  of  how  to  think

     in  React   •  See  some  actual  React  in  Prac0ce   •  Get  a  basic  understanding  of  tes0ng  React   •  Introduc0on  to  the  concept  of  unidirec0onal   dataflow  as  an  “alterna$ve”  to  MVC   •  See  ReactNa0ve   •  Play  with  some  examples  
  58. Useful  Resources   •  [ReactJS](h?p://facebook.github.io/react/)   •  [ReactJSConf]   (h?p://conf.reactjs.com/schedule.html)

      •  [ReactJSNews](h?ps://reactjsnews.com/)   •  [Immutable.js]   (h?p://facebook.github.io/immutable-­‐js/)   •  [CSS  in  JS]   (h?ps://speakerdeck.com/vjeux/react-­‐css-­‐in-­‐js)  
  59. More  Useful  Resources   •  [Thinking  in  React]   (h?p://facebook.github.io/react/docs/

      thinking-­‐in-­‐react.html)   •  [Egghead.io]   (h?ps://egghead.io/technologies/react)   •  [Khan  Academy]   (h?p://khan.github.io/react-­‐components/)