isomorphic react in real life

34
Isomorphic React In Real Life Jonas Ohlsson @pocketjoso

Upload: london-react-user-group

Post on 15-Jul-2015

150 views

Category:

Technology


0 download

TRANSCRIPT

Isomorphic React

In Real Life

Jonas Ohlsson

@pocketjoso

Who am I?

• Frond end developer at State

• Performance, tooling and open source geek

Isomorphic new site: http://alpha.state.com

Penthouse, Critical Path CSS Generator:

https://github.com/pocketjoso/penthouse

This talk

• Background: Isomorphism, React

• State’s isomorphic React render flow

- Data

- Bootstrap

- Stores

Isomorphic JavaScript

• Shared JS running both client and server

• Performance, graceful degradation, Accessibility, SEO

Flash of Client Side Rendering

Isomorphic React

• Easy - React.renderToString()

• What about data fetching, re-using render state, stores

React render flow (client)

URL RenderFetch

data

Routing

table

React render flow (client)

RenderFetch

data

Routing

tableURL

props = {

page: ExplorePage

};

React render flow (client)

RenderFetch

data

Routing

tableURL

props = {

page: ExplorePage

};

React.render(

<App {…props} />,

containerElement

);

React render flow (client)

React Lifecycle method componentDidMount: http://facebook.github.io/react/docs/component-specs.html#mounting-componentdidmount

RenderFetch

data

Routing

tableURL

props = {

page: ExplorePage

};

React.render(

<App {…props} />,

containerElement

);

componentDidMount

React render flow (client)

RenderFetch

data

Routing

tableURL

props = {

page: ExplorePage

};

React.render(

<App {…props} />,

containerElement

);

componentDidMount

$.get().then(result){

this.setState({data:

result});

});

React render flow (client)

props = {

page: ExplorePage

};

can’t use on the server

RenderFetch

data

Routing

tableURL

React.render(

<App {…props} />,

containerElement

);

componentDidMount

$.get().then(result){

this.setState({data:

result});

});

Isomorphic Render Flow

Isomorphic React render flow

Make requests

page asked for

React.

render/

renderToString(

<App {…props} />

);

Pre fetch

dataRender

Routing

tableURL

props = {

page: ExplorePage

};

Isomorphic React render flow

Make requests

page asked for

React.

render/

renderToString(

<App {…props} />

);

Pre fetch

dataRender

Routing

tableURL

props = {

page: ExplorePage

};

Pre data fetching

React Statics component property: http://facebook.github.io/react/docs/component-specs.html#statics

Isomorphic React render flow

data =

ExplorePage.

requestForProps();

Routing

tableURL

Pre fetch

dataRender

React.

render/

renderToString(

<App {…props} />

);

props = {

page: ExplorePage

};

Isomorphic React render flow

data =

ExplorePage.

requestForProps();

props.data = data;

Routing

tableURL

Pre fetch

dataRender

React.

render/

renderToString(

<App {…props} />

);

props = {

page: ExplorePage

};

Bootstrapping render context

React.render(

<App {…props}/>

);

Server Client

React.renderToString(

<App {…props}/>

);

Bootstrapping

Server Client

Bootstrapping render context

Flux

• Data changing over time (during a session)

• Cached data

Should I use Flux? https://medium.com/@dan_abramov/the-case-for-flux-379b7d1982c6

Flux

• Data changing over time (during a session)

• Cached data

Should I use Flux? https://medium.com/@dan_abramov/the-case-for-flux-379b7d1982c6

Isomorphic Flux Stores

Snapshot / restore

Add snapshots to render context JSON Restore on client

Store reset

• Stores are singletons

• Prevent data leaking

Stores listening for request data

Request

response

data

Distribute StoresNormalise

Stores listening for request data

Request

response

data

Distribute StoresNormalise

statement : {

creator : {

id : 12312,

name: Jonas

},

id: 199,

text: ‘This is …’

}

Stores listening for request data

Normalize data: https://github.com/gaearon/normalizr

Request

response

data

Distribute Stores

statement : {

creator : {

id : 12312,

name: Jonas

},

id: 199,

text: ‘This is …’

}

entities: {

users: {

12312: {

name: Jonas

}

},

statements: {

199: {

text: ‘This is …’

creator: 12312

}

}

}

Normalise

Stores listening for request data

Request

response

data

Distribute StoresNormalise

trigger(users)

trigger(statements)

statement : {

creator : {

id : 12312,

name: Jonas

},

id: 199,

text: ‘This is …’

}

entities: {

users: {

12312: {

name: Jonas

}

},

statements: {

199: {

text: ‘This is …’

creator: 12312

}

}

}

Stores listening for request data

UserStore = {

listenTo(

userProvider,

function(users){

// merge new users

// to store’s data

}

}

Request

response

data

Distribute Stores

statement : {

creator : {

id : 12312,

name: Jonas

},

id: 199,

text: ‘This is …’

}

Normalise

trigger(users)

trigger(statements)

entities: {

users: {

12312: {

name: Jonas

}

},

statements: {

199: {

text: ‘This is …’

creator: 12312

}

}

}

Full Render sequence: Server

• (Start stores when booting server)

• Execute requests via requestForProps for Page

• Distribute data to Stores (if not Automatic)

• React.RenderToString()

• Snapshot Stores, create render context JSON

• Send HTML to client

• Reset Stores

Full Render sequence: Client

• Parse render context JSON

• Start stores, and restore via snapshots

• React.render, with props from render context

Summary

• Fetch data before rendering React

• Statics to co-locate data requests with component logic

• Bootstrap server render context

• Snapshot, restore and reset Stores

• Optional: Auto distribute request data to Stores

Questions?@pocketjoso

Blog post based on this talk

http://jonassebastianohlsson.com/blog/2015/03/24/isomorphic-react-in-real-life/