React in the Real World
Simen Brekken (@simenbrekken)
Daniel Mahal (@danielmahal)
github.com/unfoldoslo
- React
- Vårt siste store prosjekt Anton Sport
- URL, applikasjonsstate og ruting
- Data flyt og "stores"
- Interaksjon og "actions"
- Server-side rendering og isomorfiske applikasjoner
- Testing med Jest
- Webpack
- Animasjon og CSS
Design byrå
Sterkt tekniskt fokus
Praktisk tilnærming, prototyping og eksperimentering
React
Anton Sport
Komplisert Data
Produkt
Farge
Størrelse
Pris
Prismodell
{
"id": 7,
"status": "fulfilled",
"items": [{
"status": "fulfilled",
"shippedQuantity": 1,
"returnedQuantity": 0,
"id": 11,
"productName": "Alpine Jacket",
"brandName": "PUMA",
"variantName": "Blue",
"size": "S",
"ean": 217445280878,
"quantity": 1,
"price": 299.0,
"vat": 59.8,
"total": 299.0,
"variant": {
"id": 1108,
"ean": 217445280878,
"name": "Blue",
"images": [{
"id": "products/u5k4pz8mhkns2drq6hcz",
"height": 1710,
"width": 1080
}],
"price": {
"retail": 2999.0,
"normal": 2999.0,
"discounted": 300.0,
"campaign": null,
"current": {
"type": 2,
"price": 300.0,
"vat": 60.0
},
"vat": 25.0
},
"size": "S",
"extArticleId": null,
"stock": {
"available": 0,
"threshold": 0
}
},
"product": {
"id": 1051,
"name": "Alpine Jacket",
"description": "Intern link: [Merker](/merker)\n\nEkstern link: [Google](http://google.com)",
"shortDescription": "Denne nye modellen fra Bjørn Dæhlie er laget i et 2-lags elastisk softshellmateriale",
"brand": {
"id": 1010,
"name": "PUMA",
"logo": {
"id": "0",
"width": null,
"height": null
}
},
"tags": ["AntonSportWebShopAPI.Models.Tag", "AntonSportWebShopAPI.Models.Tag", "AntonSportWebShopAPI.Models.Tag"],
"packageSize": "Normal",
"currentPrice": 190.0,
"version": "AAAAAAAACyo=",
"createdAt": "2014-11-05T15:34:44.717+00:00",
"modifiedAt": "2014-11-24T20:44:01.533+00:00",
"createdBy": "0",
"modifiedBy": "0"
}
}],
"customer": {
"name": "S",
"email": "simen@unfold.no",
"mobile": null
},
"shipping": {
"address": {
"street": "Pilestredet Park 20",
"postalCode": "0176",
"locality": "OSLO",
"countryCode": "no",
"country": "Norway"
},
"service": {
"id": 3,
"name": "Levert på dør kveld ",
"description": null,
"supplier": null,
"estimatedDelivery": null,
"price": 119.0,
"vat": 37.1875
},
"tracking": {
"mobile": null
}
},
"fulfillments": [{
"id": 10,
"status": "shipped",
"service": {
"id": 1,
"name": "consignor",
"trackingCode": null,
"referenceId": null,
"trackingUrl": null
},
"items": [{
"id": 11,
"productName": "Alpine Jacket",
"brandName": "PUMA",
"variantName": "Blue",
"size": "S",
"ean": 217445280878,
"quantity": 1,
"price": 299.0,
"vat": 59.8,
"total": 299.0,
"variant": {
"id": 1108,
"ean": 217445280878,
"name": "Blue",
"images": [{
"id": "products/u5k4pz8mhkns2drq6hcz",
"height": 1710,
"width": 1080
}],
"price": {
"retail": 2999.0,
"normal": 2999.0,
"discounted": 300.0,
"campaign": null,
"current": {
"type": 2,
"price": 300.0,
"vat": 60.0
},
"vat": 25.0
},
"size": "S",
"extArticleId": null,
"stock": {
"available": 0,
"threshold": 0
}
},
"product": {
"id": 1051,
"name": "Alpine Jacket",
"description": "Intern link: [Merker](/merker)\n\nEkstern link: [Google](http://google.com)",
"shortDescription": "Denne nye modellen fra Bjørn Dæhlie er laget i et 2-lags elastisk softshellmateriale",
"brand": {
"id": 1010,
"name": "PUMA",
"logo": {
"id": "0",
"width": null,
"height": null
}
},
"tags": ["AntonSportWebShopAPI.Models.Tag", "AntonSportWebShopAPI.Models.Tag", "AntonSportWebShopAPI.Models.Tag"],
"packageSize": "Normal",
"currentPrice": 190.0,
"version": "AAAAAAAACyo=",
"createdAt": "2014-11-05T15:34:44.717+00:00",
"modifiedAt": "2014-11-24T20:44:01.533+00:00",
"createdBy": "0",
"modifiedBy": "0"
}
}],
"message": "Test kommentar"
}],
"returns": [],
"total": 418.0,
"vat": 96.9875,
"payment": {
"partial": null,
"id": 1,
"type": 1,
"price": 0.0,
"vat": 0.0,
"name": "Kortbetaling",
"details": {
"chargeId": "ch_14yMWNKYEVdyeGxGly0lCqvo"
},
"transactions": [{
"id": 7,
"type": "Authorize",
"transactionReference": "ch_14yMWNKYEVdyeGxGly0lCqvo",
"amount": 418.0
}]
},
"account": null,
"comments": null,
"createdAt": "2014-11-13T12:16:19.887+00:00",
"modifiedAt": "2014-11-17T08:29:14.88+00:00",
"createdBy": "0",
"modifiedBy": "0"
}
Organisering
Små komponenter
Komposisjon
Anton består av 300+ individuelle komponenter
Naturlig navngivning
Enkelt å navigere
URL & Applikasjonsstate
Request & Response
Imitasjon av native apps
URL = Applikasjonsstate
Ruting skjema gir oversikt
<Route handler={Application}>
<Route path="products" handler={Products}>
<Route path=":product" handler={Product} />
<DefaultRoute handler={ProductList} />
</Route>
<Route path="checkout" handler={Checkout} />
</Route>
/products/flippin-snowboard
Application
Products
Product
/products
/
Dataflyt
Application
Sidebar
Cart
cartItems
cartItems
Top down
Component
Data (props)
onAddCartItem
onUpdateCartItem
onRemoveCartItem
onAddCartItem
onUpdateCartItem
onRemoveCartItem
onAddCartItem
onUpdateCartItem
onRemoveCartItem
cartItems
Methods (props)
Product
Cart
Category
Stores
Cart
Lese fra Stores
Component
getItems
getTotal
etc.
Skrive til Stores
A
B
C
A
Skrive til Stores
med Actions
Cart
Component
Action
Flux
Reflux
Relay & GraphQL
Server-side rendering
- Pre-rendre statisk HTML
- Klienten kobler seg på eksisterende DOM
- SEO & Tilgjengelighet
- Vær forsiktig med "window" og "document"
- Isomorfiske biblioteker (f.eks. superagent)
- Caching
Testing med Jest
- Automatisk mocking
- Testing av moduler i isolasjon
- Simulering av browser events
Testing med Jest
var Product = require('../Product')
var Actions = require('../Actions')
describe('Add to cart button', function() {
it('should fire an add to cart action when clicked', function() {
var props = {id: 1}
var component = ReactTest.renderIntoDocument(Product(props))
var button = ReactTest.findComponentWithClass(component, 'add-to-cart')
ReactTest.Simulate.click(button)
expect(Actions.addToCart).toBeCalledWith({productId: 1})
})
})
Testing av et komponent
Webpack
Bundling av scripts, styles og assets
Splitting og dynamisk lasting av bundles
Multi-device testing
React Hot Module Loading
Transpiling ES6, JSX etc. via Babel
React Hot Loader
Live Demo (#YOLO)
ReactCSSTransitionGroup
ReactTransitionGroup
AnimationMixin
Cheng Lou
react-tween-state, react-state-stream
Animasjon = Pain
React ‹-› CSS ?
Start tidlig med ruting
Hold komponenter små (composition)
Sentraliser datahåndtering
Frakoble brukerinteraksjoner med actions
Gjenbruk server og klient kode, få ytelse gratis!
Fortsatt noen ting som er knotete (animasjoner og CSS)
Oppsummering
Takk!
Simen Brekken (@simenbrekken)
Daniel Mahal (@danielmahal)
github.com/simenbrekken
React in the Real World
By Simen Brekken
React in the Real World
- 1,086