Workshop React.js

100

Click here to load reader

Transcript of Workshop React.js

Page 1: Workshop React.js

ES6, REACT AND REDUX

Page 2: Workshop React.js

MICHELE CARRÌ @KEOWN [email protected]

GIANLUCA PADOVANI @GPAD619 [email protected]

PASSIONATE DEVELOPERS CTO & FOUNDERS @CODERS51

Page 3: Workshop React.js

ES6, REACT AND REDUX

‣ ES6 ‣ React ‣ Redux ‣ Demo ‣ Case History

TOPICS

Page 4: Workshop React.js

A SHORT INTRO…

Page 5: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015

‣ Variable types ‣ Arrow functions ‣ Modules ‣ Classes ‣ A lot more…

WHAT’S NEW?

Complete Feature List: http://es6-features.org/

Page 6: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015IMMUTABLE VARIABLES

1 const MY_CONSTANT = 1; 2 MY_CONSTANT = 2 // Error

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

Page 7: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015BLOCK-SCOPED VARIABLES 1 if(true) { 2 let x = 1; 3 } 4 console.log(x); // undefined 5 6 7 for(let i = 0, l = list.length; i < l; i++) { 8 // do something with list[i] 9 } 10 11 console.log(i); // undefined

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

Page 8: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015ARROW FUNCTIONS

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

1 let books = [ 2 {title: 'X', price: 10}, 3 {title: 'Y', price: 15} 4 ]; 5 6 let titles = books.map( item => item.title ); 7 8 // ES5 equivalent: 9 var titles = books.map(function(item) { 10 return item.title; 11 });

Page 9: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015ARROW FUNCTIONS

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

1 let book = { 2 title: 'X', 3 sellers: ['A', 'B'], 4 printSellers() { 5 this.sellers.forEach((seller) => { 6 console.log(seller + ' sells ' + this.title); 7 }); 8 } 9 }

Page 10: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015ARROW FUNCTIONS

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

1 // ES5 equivalent: 2 var book = { 3 title: 'X', 4 sellers: ['A', 'B'], 5 printSellers: function() { 6 var that = this; 7 this.sellers.forEach(function(seller) { 8 console.log(seller + ' sells ' + that.title) 9 }) 10 } 11 }

Page 11: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015MODULES 1 // lib/math.js 2 3 export function sum(x, y) { 4 return x + y; 5 } 6 export var pi = 3.141593;

1 // app.js 2 3 import { sum, pi } from "lib/math"; 4 console.log('PiGreco = ' + sum(pi, pi));

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

Page 12: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015MODULES 1 // lib/my-fn.js 2 3 export default function() { 4 console.log('echo echo'); 5 }

1 // app.js 2 3 import doSomething from 'lib/my-fn'; 4 doSomething();

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

Page 13: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015

1 class Vehicle { 2 constructor(name) { 3 this.name = name; 4 this.kind = 'vehicle'; 5 } 6 getName() { 7 return this.name; 8 } 9 } 10 11 // Create an instance 12 let myVehicle = new Vehicle('rocky');

CLASSES

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

Page 14: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015CLASSES 1 class Car extends Vehicle { 2 constructor(name) { 3 super(name); 4 this.kind = ‘car'; 5 } 6 } 7 8 let myCar = new Car('bumpy'); 9 10 myCar.getName(); // 'bumpy' 11 myCar instanceof Car; // true 12 myCar instanceof Vehicle; //true

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

Page 15: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015SPREAD OPERATOR

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

1 let values = [1, 2, 4]; 2 let some = [...values, 8]; 3 // [1, 2, 4, 8] 4 5 let more = [...values, 8, ...values]; 6 // [1, 2, 4, 8, 1, 2, 4] 7 8 // ES5 equivalent: 9 let values = [1, 2, 4]; 10 // Iterate, push, sweat, repeat... 11 // Iterate, push, sweat, repeat...

Page 16: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015SPREAD OPERATOR

https://www.smashingmagazine.com/2015/10/es6-whats-new-next-version-javascript/

1 let values = [1, 2, 4]; 2 3 doSomething(...values); 4 5 function doSomething(x, y, z) { 6 // x = 1, y = 2, z = 4 7 } 8 9 // ES5 equivalent: 10 doSomething.apply(null, values);

Page 17: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015SO, WHAT EXACTLY CAN I USE?

Browsers Support inconsistent between browsers. Microsoft Edge is one best in ES6 support. :-)

Node Partial support. Some features are available only on versions > 5 and need to be explicitly enabled with a runtime flag.

Page 18: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015SO, WHAT EXACTLY CAN I USE?

https://babeljs.io

Page 19: Workshop React.js

ECMASCRIPT 6 / ECMASCRIPT 2015BABEL

Page 20: Workshop React.js

LET’S TALK ABOUT REACT

Page 21: Workshop React.js

REACT IS A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES

Page 22: Workshop React.js

REACT IS NOT A FRAMEWORK

Page 23: Workshop React.js

https://facebook.github.io/react/

REACT

Page 24: Workshop React.js

REACTJUST FOR THE UIReact is all about modular, composable components. Not necessarily web components.

It makes no assumptions about the rest of your technology stack.

Page 25: Workshop React.js

REACTVIRTUAL DOM

Keep track of state in DOM is hard!

It’ll be so easier to re-render the whole DOM on every change.

Unfortunately the DOM API is not so fast.

Page 26: Workshop React.js

REACTVIRTUAL DOM

http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html

Page 27: Workshop React.js

REACTVIRTUAL DOM

http://teropa.info/blog/2015/03/02/change-and-its-detection-in-javascript-frameworks.html

Page 28: Workshop React.js

REACTVIRTUAL DOM

‣ Batched DOM read/write operations ‣ Efficient update of sub-tree only

Page 29: Workshop React.js

REACTONE WAY DATA FLOW

The only way to pass data thought different components is from top to bottom. No two way bindings.

Page 30: Workshop React.js

REACTJSX

return <div>Hello {this.props.name}</div>;

React components are written in JSX, a JavaScript extension syntax allowing easy quoting of HTML and using HTML tag syntax to render components.

Page 31: Workshop React.js

REACTLET’S CREATE A COMPONENT! 1 // hello_message.js 2 3 import React from 'react'; 4 import ReactDOM from 'react-dom'; 5 6 class HelloMessage extends React.Component { 7 render() { 8 return <div>Hello {this.props.name}</div>; 9 } 10 } 11 12 const mountNode = document.getElementById('example'); 13 ReactDOM.render(<HelloMessage name="John" />, mountNode);

Page 32: Workshop React.js

REACTPROPS‣ Props contain anything you need to

render your component ‣ You can use string, functions, objects or

arrays as a prop ‣ Props should be considered immutable ‣ Mutating props is bad

Page 33: Workshop React.js

REACTPROPTYPESPropTypes defines type and which props are required. 1 //example 1 2 MyComponent.propTypes = { 3 size: React.PropTypes.number, 4 position: React.PropTypes.string.isRequired 5 } 6 7 //example 2 8 MyComponent.propTypes ={ 9 position: React.PropTypes.oneOf(['fixed', 'absolute']) 10 }

Page 34: Workshop React.js

REACTPROPTYPES 1 //example 3 2 3 MyComponent.propTypes = { 4 email: (props, propName, componentName) => { 5 if (!/emailRegex/.test(props[email])) { 6 return new Error('Give me a real email!'); 7 } 8 }, 9 user: React.PropTypes.shape({ 10 name: React.PropTypes.string.isRequired, 11 age: React.PropTypes.number 12 }).isRequired 13 }

Page 35: Workshop React.js

REACTNESTED COMPONENTS 1 // profile.js 2 3 import React from 'react'; 4 5 class Profile extends React.Component{ 6 render(){ 7 return ( 8 <div> 9 <img src={this.props.avatar} /> 10 <span>{this.props.name}</span> 11 </div> 12 ); 13 } 14 }

Page 36: Workshop React.js

REACTNESTED COMPONENTS 1 // app.js 2 3 import React from 'react'; 4 import ReactDOM from 'react-dom'; 5 import Profile from './profile'; 6 7 class App extends React.Component{ 8 render(){ 9 return ( 10 <div> 11 <h1>Hello World!</h1> 12 <Profile avatar="http://test.png" name="Nik" /> 13 </div> 14 ); 15 } 16 } 17 18 const exampleNode = document.getElementById('example'); 19 ReactDOM.render(<App />, exampleNode);

Page 37: Workshop React.js

REACTIF/ELSE (1) 1 // profile.js 2 3 import React from 'react'; 4 5 class Profile extends React.Component{ 6 render(){ 7 8 let AdminIcon; 9 10 if (this.props.isAdmin) { 11 AdminIcon = (<span>green</span>); 12 } 13

Page 38: Workshop React.js

REACTIF/ELSE (2)

14 return ( 15 <div> 16 <img src={this.props.avatar} /> 17 <span>{this.props.name}</span> 18 {AdminIcon} 19 </div> 20 ); 21 } 22 }

Page 39: Workshop React.js

REACTLOOPS 1 // list.js 2 3 import React from 'react'; 4 5 class List extends React.Component{ 6 render(){ 7 return ( 8 <ul> 9 {this.props.friends.map((friend) => { 10 return <li>{friend.name}</li>; 11 })} 12 </ul> 13 ); 14 } 15 }

Page 40: Workshop React.js

REACTINTERACTIONS 1 // profile.js 2 3 import React from 'react'; 4 5 class Profile extends React.Component{ 6 7 notify(){ 8 console.log('NOCIIIIII!') 9 } 10 11 render(){ 12 return ( 13 <div onClick={(e) => this.notify(e)}> 14 <img src={this.props.avatar} /> 15 <span>{this.props.name}</span> 16 </div> 17 ); 18 } 19 }

Page 41: Workshop React.js

REACTSTATE AND SET STATE

‣ state is a property that can keep the component state

‣ setState is a function that change the current state ‣ when setState is called the component

automatically call render again

Page 42: Workshop React.js

REACTLET’S CREATE A STATEFUL COMPONENT! 1 // like_button.js 2 3 import React from 'react'; 4 import ReactDOM from 'react-dom'; 5 6 class LikeButton extends React.Component { 7 constructor(){ 8 super(); 9 this.state = {liked: false}; 10 } 11 handleClick() { 12 this.setState({liked: !this.state.liked}); 13 }

Page 43: Workshop React.js

REACTLET’S CREATE A STATEFUL COMPONENT!

14 render() { 15 var text = this.state.liked ? 'like' : 'haven\'t liked'; 16 return ( 17 <p onClick={this.handleClick}> 18 You {text} this. Click to toggle. 19 </p> 20 ); 21 } 22 } 23 24 const mountNode = document.getElementById('example'); 25 ReactDOM.render(<LikeButton />, mountNode);

Page 44: Workshop React.js

REACTCOMPONENT STATE‣ Most of your components should simply take

some data from props and render it. ‣ State should contain data that a component's

event handlers may change to trigger a UI update.

‣ Try to keep as many of your components as possible stateless.

Page 45: Workshop React.js

REACTNOT ONLY ON THE DOM…

The react-dom/server package allows you to render your components on the server.

Page 46: Workshop React.js

REACTSERVER SIDE RENDERING 1 // hello_message.js 2 3 import React from 'react'; 4 import ReactDOMServer from 'react-dom/server'; 5 6 class HelloMessage extends React.Component { 7 render() { 8 return <div>Hello {this.props.name}</div>; 9 } 10 } 11 12 ReactDOMServer.renderToString(<HelloMessage />);

Page 47: Workshop React.js

REACTNOT ONLY ON THE DOM…

You can even build almost native mobile applications!

Page 48: Workshop React.js

REACTREACT NATIVE

‣ Same programming paradigm of React ‣ Javascript is executed by iOS / Android ‣ RN “bridge” invokes the native rendering APIs in

Objective-C / Java ‣ RN works separately from the main UI thread ‣ You can still write native code and a bridge for js

Page 49: Workshop React.js

REACTREACT NATIVE 1 // iOS 2 3 var React = require('react-native'); 4 var { TabBarIOS, NavigatorIOS } = React; 5 6 var App = React.createClass({ 7 render: function() { 8 return ( 9 <TabBarIOS> 10 <TabBarIOS.Item title="React Native" selected={true}> 11 <NavigatorIOS initialRoute={{ title: 'React Native' }} /> 12 </TabBarIOS.Item> 13 </TabBarIOS> 14 ); 15 }, 16 });

Page 50: Workshop React.js

REACTTESTING

‣ Jest - https://facebook.github.io/jest ‣ Mocha ‣ Jasmine

‣ React Test Utilities ‣ Enzyme - https://github.com/airbnb/enzyme

Page 51: Workshop React.js

REACTSUMMARY

‣ We can build components ‣ We can build an applications with several

different components ‣ We can keep our application state inside the state

of our components

Page 52: Workshop React.js

REACTSUMMARY

But wait… shouldn’t React only deal with the UI?

OK, GREAT!

Page 53: Workshop React.js

REACTSUMMARY

Be careful because maintaining your application state within the state of your components isn’t a great idea…

Page 54: Workshop React.js

REACTSUMMARY

So where should i keep the application state and how it changes?

Page 55: Workshop React.js

REDUXhttp://redux.js.org

Page 56: Workshop React.js

REDUXWHAAAAT?

Redux allows you to manage the state with a minimal API but completely predictable behaviour.

Page 57: Workshop React.js

REDUXTHE APPLICATION STATE 1 { 2 todos: [ 3 { 4 text: 'Learn React', 5 completed: true 6 }, 7 { 8 text: 'Learn Redux', 9 completed: false 10 } 11 ] 12 }

Page 58: Workshop React.js

Thanks to André “Staltz” Medeiros @andresaltz

Page 59: Workshop React.js

REDUXBASICS

(previousState, action) => newState

Page 60: Workshop React.js

REDUXACTIONS

1 const action = { 2 type: 'ADD_TODO', 3 text: 'Send a message to GPad!', 4 }

Page 61: Workshop React.js

REDUXACTION CREATORS

1 function addTodo(text) { 2 return { 3 type: 'ADD_TODO', 4 text: text 5 } 6 }

Page 62: Workshop React.js

REDUXDISPATCH AN ACTION

dispatch(addTodo('Send a message to GPad!'));

Page 63: Workshop React.js

REDUXREDUCERS 1 const todos = (state = [], action) => { 2 switch (action.type) { 3 case 'ADD_TODO': 4 return [ 5 ...state, 6 { 7 text: action.text, 8 completed: false 9 } 10 ] 11 default: 12 return state 13 } 14 }

Page 64: Workshop React.js

REDUXREDUCERS

Expect you to return a copy of the state, not mutate it.

Page 65: Workshop React.js

REDUXINSPIRED BY ELM

1 type Action = Increment | Decrement 2 3 update action model = 4 case action of 5 Increment -> model + 1 6 Decrement -> model - 1

http://elm-lang.org

Page 66: Workshop React.js

REDUXSTORE 1 import { createStore } from 'redux'; 2 import todoReducer from '../reducers'; 3 4 let store = createStore(todoReducer); 5 6 store.subscribe( 7 () => console.log(store.getState()) 8 ) 9 10 store.dispatch(addTodo('Send a message to GPad!')); 11 store.dispatch(addTodo('Send a message to mk!'));

Page 67: Workshop React.js

REDUXASYNC ACTION CREATORS

In Javascript actions are not always synchronous (example: ajax calls)

Page 68: Workshop React.js

REDUXASYNC ACTION CREATORS

1 function fetch() 2 return dispatch => { 3 dispatch(loadingAction()); 4 doSomeAjax(...) 5 .then(function(response) { 6 dispatch(successAction, successAction(response.data)); 7 } 8 } 9 }

Page 69: Workshop React.js

REDUXMIDDLEWARE

‣ Logging ‣ Async actions ‣ Dev tools

Page 70: Workshop React.js

REDUXNOT REACT SPECIFIC!

It’s just an event and state management library!

Page 71: Workshop React.js

REDUXREACT + REDUX 1 import React from 'react'; 2 import ReactDOM from 'react-dom'; 3 import { createStore } from 'redux'; 4 5 import { Provider } from 'react-redux'; 6 7 import todoApp from './reducers'; 8 import App from './components/App'; 9 10 let store = createStore(todoApp); 11 12 let exampleNode = document.getElementById('example'); 13 14 ReactDOM.render( 15 <Provider store={store}> 16 <App /> 17 </Provider>, 18 exampleNode 19 );

Page 72: Workshop React.js

REDUXREACT + REDUX 1 import React from 'react'; 2 import { connect } from 'react-redux'; 3 import { addTodo } from '../actions.js'; 4 5 class App extends React.Component { 6 render(){ 7 const { dispatch } = this.props; 8 return( 9 <button onClick={ dispatch(addTodo('Call GPad!')) }> 10 Add Todo 11 </button> 12 ); 13 } 14 } 15 16 export default connect((state) => state)(App)

Page 73: Workshop React.js

REDUXSMART AND DUMP COMPONENTS

Technically all components could be connect to the store but that’s a very bad idea!

Page 74: Workshop React.js

REDUXSMART AND DUMP COMPONENTS

The best behavior is to connect only top level components and pass actions to other components using props.

Page 75: Workshop React.js

REDUXSMART AND DUMP COMPONENTS 1 // app.js 2 3 import React from 'react'; 4 import Profile from './profile'; 5 import { connect } from 'react-redux'; 6 import { openModal } from '../actions'; 7 8 9 class App extends React.Component{ 10 11 clickHandler(){ 12 const { dispatch } = this.props; 13 dispatch(openModal()); 14 } 15

Page 76: Workshop React.js

REDUXSMART AND DUMP COMPONENTS 16 render(){ 17 return ( 18 <div> 19 <h1>Hello World!</h1> 20 <Profile avatar="http://test.png" 21 name="Nik" 22 onImageClick={() => this.clickHandler()}/> 23 </div> 24 ); 25 } 26 } 27 28 export default connect((state) => state)(App)

Page 77: Workshop React.js

REDUXSMART AND DUMP COMPONENTS 1 // profile.js 2 3 import React from 'react'; 4 5 class Profile extends React.Component{ 6 render(){ 7 return ( 8 <div> 9 <img src={this.props.avatar} onClick={this.props.onImageClick}/> 10 <span>{this.props.name}</span> 11 </div> 12 ); 13 } 14 } 15 16 export default Profile;

Page 78: Workshop React.js

REDUXTESTING

http://rackt.org/redux/docs/recipes/WritingTests.html

Testing Redux is pretty easy because action creators and reducers are just functions.

Page 79: Workshop React.js

REDUXSUMMARY

‣ Reusable Components ‣ Easy to understand ‣ Performant & Lightweight ‣ Reducers are very easy to test

Page 80: Workshop React.js

REACT & REDUXARE THEY PRODUCTION READY?

React - Used by Facebook, AirBnb and many more…

Redux - Used by Firefox, Docker, coders51 and many more… :-)

Page 81: Workshop React.js

REACT & REDUXSUPPORT

‣ https://facebook.github.io/react/ ‣ http://redux.js.org ‣ https://egghead.io/series/getting-

started-with-redux

Page 82: Workshop React.js

?

Page 83: Workshop React.js

REACT & REDUX

ONE MORE THING…

Page 84: Workshop React.js

REACT & REDUX

TIME TRAVEL DEMO

Page 85: Workshop React.js

?

Page 86: Workshop React.js

CASE HISTORY

Page 87: Workshop React.js

CASE HISTORY 1CURRENT SCENARIO & REQUESTS

‣ Customer with several different applications (Rails, Wordpress, etc)

‣ Need a way to show how much time is left to the release date of a film

Page 88: Workshop React.js

CASE HISTORY 1SOLUTION

Javascript library that mounts a React component. The component fetch the data needed from an api and show the countdown.

Page 89: Workshop React.js

CASE HISTORY 1PRO

‣ No code duplication across different apps ‣ Easily embeddable by anyone in any stack

Page 90: Workshop React.js

CASE HISTORY 2CURRENT SCENARIO

‣ Medium size Rails app already in production ‣ Growing ecosystem with several different

applications ‣ Need to share some common basic features

between every application

Page 91: Workshop React.js

CASE HISTORY 2REQUESTED FEATURES

‣ Toolbar ‣ Real time notifications ‣ Friendship Management ‣ Internationalization Management ‣ Banner Management ‣ Footer

Page 92: Workshop React.js

CASE HISTORY 2SOLUTION

Javascript components library with some great APIs to interact with the underlying applications.

Page 93: Workshop React.js

CASE HISTORY 2PRO

‣ No code duplication across different apps ‣ Consistent way to manage real time

notifications and messaging via websocket ‣ Easily embeddable in any stack

Page 94: Workshop React.js

CASE HISTORY 3CURRENT SCENARIO

‣ HUGE size Rails app already in production ‣ Several pages with large list of articles (very

similar to a Facebook timeline…) ‣ A lot of duplicated code ‣ Poor rendering performance ‣ jQuery + Handlebars

Page 95: Workshop React.js

CASE HISTORY 3REQUESTED FEATURES

‣ Speed up render process ‣ SEO friendly

Page 96: Workshop React.js

CASE HISTORY 3SOLUTION

Timeline is now a react component and it’s rendered both server side and client side (if needed)

Page 97: Workshop React.js

CASE HISTORY 3PRO

‣ No code duplication (server side rendering) ‣ No more DOM based code ‣ More readable and testable code ‣ Fast

Page 98: Workshop React.js

?

Page 99: Workshop React.js

THANKS EVERYBODY!