Top Banner
A JOURNEY WITH REACT TASVEER SINGH @tazsingh
54

A Journey with React

Mar 16, 2018

Download

Internet

FITC
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: A Journey with React

A J O U R N E Y W I T H R E A C T

TA S V E E R S I N G H @ t a z s i n g h

Page 2: A Journey with React
Page 3: A Journey with React
Page 4: A Journey with React
Page 5: A Journey with React

3 A P P S

Page 6: A Journey with React

– M I K E H O U R A H I N E

“You can learn trigonometry, physics, C++, and DirectX to make a video game. Or you can make a video game and learn DirectX, C++, physics, and

trigonometry.”

Page 7: A Journey with React

0

100

Number of times you’ve built a similar app

1 2 3 4 5 6 7 ...

Quality

Mistakes Made

Page 8: A Journey with React

A P P # 1 - R E A C T A S A T E M P L AT I N G E N G I N E

• Server side application framework

• Nashorn JavaScript engine for Java 8

• Vert.x 2.3 - Polyglot Event-Driven Messaging

• Innovative Router

• React to describe HTML

Page 9: A Journey with React

A P P # 2 - F L U X

Page 10: A Journey with React
Page 11: A Journey with React
Page 12: A Journey with React
Page 13: A Journey with React

M

C

C

C

C

V

V

V

V

M

Page 14: A Journey with React

M

C

C

C

C

V

V

V

V

M

Page 15: A Journey with React
Page 16: A Journey with React

A P P # 2 - F L U X

• My first iteration relied on my experience from MVC

• Business logic resides in Models/Stores

• Fat models, skinny controllers

• Models/Stores make AJAX calls

• Actions were very light weight notifications to the Stores

Page 17: A Journey with React

function signInUser(username, password) { Dispatcher.dispatch({ type: ActionTypes.USER_SIGN_IN , username: username , password: password }); }

Page 18: A Journey with React

class UserStore extends EventEmitter { currentUser = null; dispatchToken = Dispatcher.register((action) => { switch(action.type) { case ActionTypes.USER_SIGN_IN: fetchUser(action.username, action.password).then( (response) => { this.currentUser = response.user; this.emit(“change”); }); } }); }

Page 19: A Journey with React

function getState() { return { currentUser: UserStore.currentUser } } class SignInComponent extends React.Component { state = getState(); handleStateChange() { this.setState(getState()); } componentDidMount() { UserStore.on(“change”, this.handleStateChange); } componentWillUnmount() { UserStore.removeListener(“change”, this.handleStateChange); } handleAuth(event) { signInUser(prompt(“What’s your username?”), prompt(“What’s your password?”)); } render() { if(!this.state.currentUser) return <a onClick={this.handleAuth}>Click here to sign in</a>; else return <p>You’re signed in as {this.state.currentUser.name}</p>; } }

Page 20: A Journey with React

A P P # 2 - F L U X - F I R S T I T E R AT I O N

• Facebook’s Dispatcher does not allow you to dispatch from a dispatch

• Difficult to compose application flow

• How do you handle errors?

• Relies on the Global State of ActionTypes

• Views worked great!

Page 21: A Journey with React

N E X T I T E R AT I O N

T R Y C O M P O S I N G A C T I O N S

Page 22: A Journey with React

class SignInUser extends BaseAction { constructor(username, password, alreadySignedInUser) { this.username = username; this.password = password; this.alreadySignedInUser = alreadySignedInUser; if(!this.alreadySignedInUser) this.authUser(); } authUser() { fetchUser(this.username, this.password).then( (newUser) => { new SignInSuccess(newUser); } , (errors) => { new SignInFailure(errors); } ); }

Page 23: A Journey with React
Page 24: A Journey with React

class SignInUser extends BaseAction { constructor(username, password, alreadySignedInUser) { this.username = username; this.password = password; this.alreadySignedInUser = alreadySignedInUser; if(!this.alreadySignedInUser) this.authUser(); } authUser() { fetchUser(this.username, this.password).then( (newUser) => { new SignInSuccess(newUser); } , (errors) => { new SignInFailure(errors); } ); }

Page 25: A Journey with React

class SignInSuccess extends BaseAction { constructor(newUser) { this.newUser = newUser; this.dispatch(); } }

class SignInFailure extends BaseAction { constructor(errors) { this.errors = errors; this.dispatch();

new FlashMessage(“Could not sign in”); } }

Page 26: A Journey with React

class UserStore extends EventEmitter { currentUser = null; dispatchToken = Dispatcher.register((action) => { switch(action.constructor) { case SignInSuccess: this.currentUser = action.newUser; this.emit(“change”); } }); }

Page 27: A Journey with React

A P P # 2 - F L U X - 2 N D I T E R AT I O N

• Eliminates the “dispatching from a dispatch” problem

• Stores are synchronous

• Very easy to compose the flow of your application by composing actions

• Eliminated Global State of ActionTypes

• Extremely scalable solution

• Easy to test

• In a later iteration, dropped in WebPack

Page 28: A Journey with React

A P P # 3 - B R O C H U R E W E B S I T E

Page 29: A Journey with React

A P P # 3 - B R O C H U R E W E B S I T E

• SEO is paramount

• AJAX is bad for SEO

• Performant on Desktop and Mobile

• Server Side Rendered

• Incremental Loading

• Introduce server side developers to client side technologies

• ES6/ES2015 via Babel

• React + Flux + WebPack

Page 30: A Journey with React

A P P # 3 - B R O C H U R E W E B S I T E

• Server side React + Server side Flux

• WebPack manages front end assets, inlining, and chunking

• Incremental loading by chunking

• Reduce number of web requests by inlining

• Koa.js serves the application and handles routing

Page 31: A Journey with React

0

100

Number of times you’ve built a similar app

1 2 3 4 5 6 7 ...

Quality

Mistakes Made

Page 32: A Journey with React

0

100

Number of times you’ve built a similar app

1 2 3 4 5 6 7 ...

Quality

Mistakes Made

Page 33: A Journey with React

0

100

Number of times you’ve built a similar app

1 2 3 4 5 6 7 ...

Quality

Mistakes Made

Page 34: A Journey with React
Page 35: A Journey with React

G R I F F I N . J S

Page 36: A Journey with React

G R I F F I N . J S

• Includes everything I’ve learnt and more

• Facebook’s Dispatcher

• React Views

• Griffin Actions - Same as previous examples

• Redux Stores w/ Griffin Connector to Views

Page 37: A Journey with React

class UserStore extends EventEmitter { currentUser = null; dispatchToken = Dispatcher.register((payload) => { switch(payload.constructor) { case SignInSuccess: this.currentUser = payload.newUser; this.emit(“change”); } }); }

Page 38: A Journey with React

class UserStore extends GriffinStore { reducer(state = null, action) => { switch(action.constructor) { case SignInSuccess: return payload.newUser; default: return state; } }); }

Page 39: A Journey with React

function getState() { return { currentUser: UserStore.currentUser } } class SignInComponent extends React.Component { state = getState(); handleStateChange() { this.setState(getState()); } componentDidMount() { UserStore.on(“change”, this.handleStateChange); } componentWillUnmount() { UserStore.removeListener(“change”, this.handleStateChange); } handleAuth(event) { signInUser(prompt(“What’s your username?”), prompt(“What’s your password?”)); } render() { if(!this.state.currentUser) return <a onClick={this.handleAuth}>Click here to sign in</a>; else return <p>You’re signed in as {this.state.currentUser.name}</p>; } }

Page 40: A Journey with React

@connect({ currentUser: UserStore })

class SignInComponent extends React.Component {

handleAuth(event) { signInUser(prompt(“What’s your username?”), prompt(“What’s your password?”)); }

render() {

if(!this.props.currentUser)

return <a onClick={this.handleAuth}>Click here to sign in</a>;

else

return <p>You’re signed in as {this.props.currentUser.name}</p>;

}

}

Page 41: A Journey with React

R E A C T D E P E N D E N C Y I N J E C T I O N

• Using props to pass in external data is similar to Angular’s dependency injection

• Only use state to manage internal component state

• <SignInComponent currentUser={{name: “Mock User!”}} />

• <SignInComponent currentUser={null} />

Page 42: A Journey with React

R E A C T R O U T E R

Page 43: A Journey with React

R E A C T R O U T E R

• Amazing routing solution - Inspired heavily by Ember’s router

• Ember has an excellent router

• Uses JSX or JSON to describe routes and nested routes

• React Component will be loaded by a Route

• Version 1.0 has lazy loading of routes and components

• Better Server Side Rendering

Page 44: A Journey with React

React.render(( <Router> <Route path="/" component={App}> <Route path="about" component={About} /> <Route path="inbox" component={Inbox}> <Route path="messages/:id" component={Message} /> </Route> </Route> </Router> ), document.body)

Page 45: A Journey with React

. ├── AppComponent.js => / ├── AboutComponent.js => /about ├── InboxComponent.js => /inbox └── MessageComponent.js => /inbox/messages/:id

Page 46: A Journey with React

. ├── AppComponent.js => / ├── AboutComponent.js => /about ├── InboxComponent.js => /inbox └── inbox    └── MessageComponent.js => /inbox/messages/:id

Page 47: A Journey with React

. ├── index.js => / ├── about │   └── index.js => /about └── inbox    ├── index.js => /inbox    └── messages    └── @id    └── index.js => /inbox/messages/:id

Page 48: A Journey with React

. ├── index.js => / ├── about │   └── index.js => /about └── inbox    ├── DeleteMessage.js    ├── GetMessages.js    ├── MessageStore.js    ├── index.js => /inbox    └── messages    └── @id    └── index.js => /inbox/messages/:id

Page 49: A Journey with React

React.render(( <Router> <Route path="/" component={App}> <Route path="about" component={About} /> <Route path="inbox" component={Inbox}> <Route path="messages/:id" component={Message} /> </Route> </Route> </Router> ), document.body)

Page 50: A Journey with React

G R I F F I N F I L E S Y S T E M B A S E D R O U T I N G

• Easy to initialize your app

• import myApp from “griffin!.”;myApp({ /* any griffin options here */});

• Easy to mount other apps

• import anotherApp from “griffin!/path/to/app”;anotherApp({ /* griffin options */});

Page 51: A Journey with React

U N I V E R S A L A P P S W I T H W E B PA C K

• Everything goes through WebPack

• Based on James Long’s excellent “Backend Apps with WebPack” posts

• On the server, it ignores CSS, images, etc.

• WebPack enables lazy-loading of application chunks

• Incrementally load Griffin routes

• Include common modules with initial payload

Page 52: A Journey with React

G R I F F I N . J S S TAT U S

• Almost ready for release

• Planning to release in the next few months

• I’m currently rewriting the WebPack incremental file-system based routing

• Last core item remaining before release

Page 53: A Journey with React

0

100

Number of times you’ve built a similar app

1 2 3 4 5 6 7 ...

Quality

Mistakes Made

Page 54: A Journey with React

T H A N K Y O U

@ t a z s i n g h