react-rails: an isomorphic match made in heaven

react-rails: an isomorphic match made in heaven

React (which is obvs so hot right now) is hot; It is also a pretty cool view layer, but you have to adopt the entire JS stack to make use of it. OR WAIT, DO YOU!?!?!?!

Let's look at how we can use the Rails asset pipeline, JSON APIs, pre-rendering, and React to build isomorphic rails apps that rule.

We'll start with a quick intro to React, and then get inside Rails to pre-render and render React on the server.

I (JWo) don't say this often, but this is a _compelling_ technology stack.

3b5cb0411cbd1012acab1b60f7ce3606?s=128

Jesse Wolgamott

October 21, 2015
Tweet

Transcript

  1. 3.

    CREATED BY FACEBOOK DESIGNED TO SOLVE THE STATE PROBLEM WITH

    JQUERY WILL RENDER WHENEVER ITS INTERNAL STATE CHANGES VERY FAST WEB COMPONENT BASED
  2. 4.

    WHY IS IT FAST? INSTEAD OF STORING IN THE DOM,

    REACT HAS ITS OWN "VIRTUAL DOM" THEN, IT SYNCS CHANGES, REUSING WHAT IT CAN https://cdn.tutsplus.com/net/uploads/2013/11/component- dom-tree.png
  3. 5.

    THE VERY BASICS EACH REACT COMPONENT MUST HAVE A "RENDER"

    FUNCTION THE RENDER FUNCTION HAS HTML INSIDE OF IT. WHEN HTML+JS ARE IN SAME FILE, WE CALL IT JSX
  4. 6.

    OHHAI Run this code 1 2 3 4 5 6

    7 hosted with ❤ by 1 hosted with ❤ by v a r O h H a i = R e a c t . c r e a t e C l a s s ( { r e n d e r ( ) { r e t u r n < d i v > < h 1 > O h H a i T h e r e ! < / h 1 > < / d i v > } } ) ; view raw ohhai.jsx GitHub R e a c t . r e n d e r ( < O h H a i > < / O h H a i > , d o c u m e n t . b o d y ) ; view raw very-later.js GitHub
  5. 7.

    YOU CAN RUN JAVASCRIPT, LIKE MAPPING Run this code 1

    2 3 4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 hosted with ❤ by v a r N u m b e r s = R e a c t . c r e a t e C l a s s ( { n u m b e r s ( ) { r e t u r n [ 3 , 4 , 5 ] ; } , r e n d e r ( ) { r e t u r n < d i v > < h 1 > T h e r e a r e { t h i s . n u m b e r s ( ) . l e n g t h } n u m b e r s < / h 1 > { t h i s . n u m b e r s ( ) . m a p ( f u n c t i o n ( i ) { r e t u r n < p > T h e r e i s { i } < / p > } ) } < / d i v > } } ) ; R e a c t . r e n d e r ( < N u m b e r s > < / N u m b e r s > , d o c u m e n t . b o d y ) ; view raw numbers.jsx GitHub
  6. 8.

    WHAT ABOUT STATE? STATE STORES THE COMPONENTS DATA. INSTEAD OF

    IN `DATA-` ATTRIBUTES A COMPONENT SETS ITS OWN STATE
  7. 9.

    CODE THAT USES STATE Run this code 1 2 3

    4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 hosted with ❤ by v a r T w e e t B o x = R e a c t . c r e a t e C l a s s ( { g e t I n i t i a l S t a t e ( ) { r e t u r n { r e m a i n i n g : 1 4 0 } } , h a n d l e K e y U p ( ) { v a r t e x t = t h i s . r e f s . t w e e t t w e e t . g e t D O M N o d e ( ) . v a l u e ; t h i s . s e t S t a t e ( { r e m a i n i n g : ( 1 4 0 - t e x t . l e n g t h ) } ) ; } , r e n d e r ( ) { r e t u r n < d i v c l a s s N a m e = " t w e e t b o x " > { t h i s . s t a t e . r e m a i n i n g } L e f t < b r / > < t e x t a r e a o n K e y U p = { t h i s . h a n d l e K e y U p } r e f = " t w e e t t w e e t " > < / t e x t a r e a > < / d i v > } } ) ; R e a c t . r e n d e r ( < T w e e t B o x > < / T w e e t B o x > , d o c u m e n t . b o d y ) ; view raw tweetbox.jsx GitHub
  8. 10.

    CODE THAT FETCHES DATA Run this code 1 2 3

    4 5 6 7 8 9 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 hosted with ❤ by v a r T a y l o r = R e a c t . c r e a t e C l a s s ( { g e t I n i t i a l S t a t e ( ) { r e t u r n { u r l s : [ ] } ; } , c o m p o n e n t D i d M o u n t ( ) { v a r c o m p o n e n t = t h i s ; f e t c h ( " h t t p : / / a p i . g i p h y . c o m / v 1 / g i f s / s e a r c h ? q = t a y l o r + s w i f t & a p i _ k e y = d c 6 z a T O x F J m z C " ) . t h e n ( f u n c t i o n ( r e s p o n s e ) { r e s p o n s e . j s o n ( ) . t h e n ( f u n c t i o n ( d a t a ) { c o m p o n e n t . s e t S t a t e ( { u r l s : d a t a . d a t a } ) ; } ) ; } ) ; } , r e n d e r ( ) { r e t u r n < d i v i d = " i m a g e s " > { t h i s . s t a t e . u r l s . m a p ( f u n c t i o n ( i m a g e ) { r e t u r n < i m g s r c = { i m a g e . i m a g e s . f i x e d _ h e i g h t . u r l } > < / i m g > } ) } < / d i v > } } ) ; R e a c t . r e n d e r ( < T a y l o r / > , d o c u m e n t . b o d y ) ; view raw taylor.jsx GitHub
  9. 11.

    WHAT ARE PROPS? PROPS ARE SENT IN FROM A PARENT

    LIKE URLS. OR LIKE THE PRODUCTS TO LOOP OVER
  10. 14.

    JAVASCRIPT BUILD SYSTEMS IF YOU DIDN'T WANT TO USE RAILS,

    YOU NEED A BUILD SYSTEM YOU NEED A ROUTER YOU NEED MANY THINGS
  11. 15.

    WITH RAILS USE RAILS' ASSET PIPELINE USE RAILS FOR AUTHENTICATION

    THE GREAT PAGE LOAD MIX OF RAILS AND REACT
  12. 19.

    REACT-RAILS A GEM. BECAUSE OF COURSE IT IS < %

    = r e a c t _ c o m p o n e n t ' T a y l o r ' % > RENDERS THE `TAYLOR` REACT COMPONENT TO THAT AREA OF THE PAGE
  13. 20.

    SENDING PROPS < % = r e a c t

    _ c o m p o n e n t ' P r o d u c t G r i d ' , { p r o d u c t s : @ p r o d u c t s } % >
  14. 21.

    SO, YOU CAN SEND PROPS TO A PRODUCTGRID IT THEN

    MAKES AN API CALL EVERY 3 SECONDS TO UPDATE INVENTORY COUNT. [END] NO NEED TO WEIRD RENDERING
  15. 25.

    < % = r e a c t _ c

    o m p o n e n t ' P r o d u c t G r i d ' , { p r o d u c t s : @ p r o d u c t s } , { p r e r e n d e r : t r u e } % >
  16. 28.

    g e m ' a c t i o n

    c a b l e ' , g i t h u b : " r a i l s / a c t i o n c a b l e " START A PUMA CABLE PROCESS HAVE A CHANNEL, AND ALSO A SUBSCRIPTION
  17. 29.

    1 2 3 4 5 6 7 8 9 1

    0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 2 0 2 1 2 2 2 3 2 4 2 5 2 6 2 7 2 8 2 9 3 0 3 1 3 2 hosted with ❤ by / / = r e q u i r e d 3 v a r C h a r t i e = R e a c t . c r e a t e C l a s s ( { g e t I n i t i a l S t a t e ( ) { r e t u r n { d a t u m : [ { " v a l u e s " : [ ] , " k e y " : " A v e r a g e " , " c o l o r " : ' # f f 7 f 0 e ' } ] } } , c o m p o n e n t W i l l U n m o u n t ( ) { A p p . v o t e s S u b c r i p t i o n = { } ; } , c o m p o n e n t W i l l M o u n t ( ) { v a r c o m p o n e n t = t h i s ; A p p . v o t e s S u b c r i p t i o n = A p p . c a b l e . s u b s c r i p t i o n s . c r e a t e ( " V o t e s C h a n n e l " , { r e c e i v e d ( d a t a ) { c o m p o n e n t . s e t S t a t e ( { d a t u m : d a t a } ) ; } } ) ; } , r e n d e r ( ) { r e t u r n < d i v > < N V D 3 C h a r t t y p e = ' l i n e C h a r t ' d a t u m = { t h i s . s t a t e . d a t u m } > < / N V D 3 C h a r t > < / d i v > } } ) ; view raw votie.jsx GitHub
  18. 30.

    BROADCAST THE VOTES THAT VOTIE LISTENS TO A c t

    i o n C a b l e . s e r v e r . b r o a d c a s t " v o t e s " , V o t e . d a t u m
  19. 31.
  20. 32.
  21. 34.

    ASSET PIPELINE -- WEBPACK TENDS TO WORK'ISH WEBPACK DEPENDENCIES ARE

    HARD YOU _COULD_ GET RID OF ASSET PIPELINE, BUT I FEEL THAT'S A BIG SPICY MEATBALL
  22. 35.

    PRERENDER TENDS TO WORK WELL, BUT RENDERING JSON IN CONTROLLER

    IS HARDER THAN YOU THINK. JUST USE ACTIVEMODELSERIALIZES