Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Add Superpowers to your React components using ...
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Siddharth Kshetrapal
January 14, 2017
Technology
380
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Add Superpowers to your React components using ES7 decorators
Siddharth Kshetrapal
January 14, 2017
More Decks by Siddharth Kshetrapal
See All by Siddharth Kshetrapal
We need to talk about our frontend workflow
siddharthkp
1
280
Advanced Component Patterns
siddharthkp
0
110
The life of CSS and it's future
siddharthkp
1
240
Building real time data heavy interfaces for SaaS
siddharthkp
1
230
A portal to the future
siddharthkp
7
2.9k
Do you even jam bruh?
siddharthkp
1
190
Designing in React
siddharthkp
0
230
ES2015 on production? Not so fast
siddharthkp
1
360
Building node modules
siddharthkp
2
520
Other Decks in Technology
See All in Technology
FinOps X 2026 Recap from Engineer Side #JapanFinOps
chacco38
0
260
アラート調査向けAIエージェントの本番導入とその後/AI Agents for Alert Investigation: Production Deployment and After
taddy_919
1
380
Compose 新機能総まとめ / What's New in Jetpack Compose
yanzm
0
130
【FinOps】データドリブンな意思決定を目指して
z63d
3
610
記録をかんたんに、提案をパーソナルに ── AIであすけんが目指すもの
oprstchn
0
140
Hatena Engineer Seminar 37 jj1uzh
jj1uzh
0
430
End-to-Endで考える信頼性 —LINEアプリにおけるクライアント開発×SRE連携の実践
maruloop
3
510
Claude Code 珍プレー好プレー
shinyasaita
0
250
プライバシー保護の理論と実践
lycorptech_jp
PRO
1
240
AI Agentをシステムに組み込む前にゆるく向き合ってみる
hayama17
0
200
認証認可だけじゃない! ID管理の構成要素と ライフサイクルを意識しよう
ritou
1
490
SRE Lounge Hiroshimaへの招待
grimoh
0
210
Featured
See All Featured
The Pragmatic Product Professional
lauravandoore
37
7.4k
Crafting Experiences
bethany
1
200
Un-Boring Meetings
codingconduct
0
330
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.4k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Testing 201, or: Great Expectations
jmmastey
46
8.2k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
28
3.5k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.1k
A brief & incomplete history of UX Design for the World Wide Web: 1989–2019
jct
2
410
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Heart Work Chapter 1 - Part 1
lfama
PRO
8
36k
Transcript
add superpowers to your React components with ES7 decorators
javascript architect @ practo @siddharthkp
ES7 decorators stage 2 https://tc39.github.io/proposal-decorators
https://babeljs.io/docs/plugins/transform-decorators/ npm install babel-plugin-transform-decorators-legacy --save
but, first template literals ES 6 Classes arrow functions
const firstName = 'siddharth' const lastName = 'kshetrapal' const fullName
= firstName + ' ' + lastName Template literals
const firstName = 'siddharth' const lastName = 'kshetrapal' const fullName
= firstName + ' ' + lastName const fullName = `${firstName} ${lastName}` Template literals
class Human { } ES 6 classes
class Human { constructor(name) { this.name = name } speak()
{ console.log(`Hi! My name is ${this.name}`) } } ES 6 classes
class Human { constructor(name) { this.name = name } speak()
{ console.log(`Hi! My name is ${this.name}`) } } const siddharth = new Human('siddharth') siddharth.speak() // Hi! My name is siddharth ES 6 classes
function log(message) { return console.log(message) } arrow functions
function log(message) { return console.log(message) } const log = (message)
=> { return console.log(message) } arrow functions
function log(message) { return console.log(message) } const log = message
=> { return console.log(message) } arrow functions
function log(message) { return console.log(message) } const log = message
=> console.log(message) arrow functions
function log(message) { return function () { return console.log(message) }
} arrow functions
arrow functions function log(message) { return function () { return
console.log(message) } } const log = message => { return () => { return console.log(message) } }
arrow functions function log(message) { return function () { return
console.log(message) } } const log = message => { return () => console.log(message) }
arrow functions function log(message) { return function () { return
console.log(message) } } const log = message => () => console.log(message)
ES7 decorators and we’re back https://tc39.github.io/proposal-decorators
class decorators class method decorators ES7 decorators
syntax class Title extends React.Component { render () { return
<div>hello {this.props.name}</div> } }
class className { func() {} } syntax
@class-decorator class className { @class-method-decorator func() {} } syntax
class className { @class-method-decorator func() {} } class method decorators
class Human { constructor(name) { this.name = name } speak()
{ console.log(`Hi! My name is ${this.name}`) } }
class Human { constructor(name) { this.name = name } speak()
{ console.log(`Hi! My name is ${this.name}`) } } const siddharth = new Human('siddharth') siddharth.speak() // Hi! My name is siddharth
... speak() { console.log(`Hi! My name is ${this.name}`) } }
const siddharth = new Human('siddharth') siddharth.speak = () => {console.log('Hi! My name is dum dum')
... speak() { console.log(`Hi! My name is ${this.name}`) } }
const siddharth = new Human('siddharth') siddharth.speak = () => {console.log('Hi! My name is dum dum') siddharth.speak() // Hi! My name is dum dum
class Human { constructor(name) { this.name = name } @readonly
speak() { console.log(`Hi! My name is ${this.name}`) } }
syntax @decorator = function const decorator = (target, key, descriptor)
=> { }
const readonly = (target, key, descriptor) => { }
const readonly = (target, key, descriptor) => { console.log(target, key,
descriptor) } /* Human {}, 'speak', { value: [Function: speak], writable: true, enumerable: false, configurable: true } */
const readonly = (target, key, descriptor) => { descriptor.writable =
false return descriptor }
@readonly speak() { console.log(`Hi! My name is ${this.name}`) } }
const siddharth = new Human('siddharth') siddharth.speak = () => {console.log('Hi! My name is dum dum'} siddharth.speak() // Hi! My name is siddharth
class Human { constructor(name) {this.name = name} useAngular() { console.log('writing
angular code') } } siddharth.writeAngular() // writing angular code
class Human { constructor(name) {this.name = name} @deprecate useAngular() {
console.log('writing angular code') } } siddharth.writeAngular() // speak@Human: this feature will be deprecated soon! // writing angular code
const deprecate = (target, key, descriptor) => { }
const deprecate = (target, key, descriptor) => { const original
= descriptor.value const name = `${target.constructor.name}.${key}` }
const deprecate = (target, key, descriptor) => { const original
= descriptor.value const name = `${target.constructor.name}.${key}` const message = 'this feature will be deprecated soon!' descriptor.value = () => { console.log(`${name} : ${message}`) original.apply(this, arguments) } }
const deprecate = (target, key, descriptor) => { const original
= descriptor.value const name = `${target.constructor.name}.${key}` const message = 'this feature will be deprecated soon!' descriptor.value = () => { console.log(`${name} : ${message}`) original.apply(this, arguments) } return descriptor }
class Human { constructor(name) {this.name = name} @deprecate useAngular() {
console.log('writing angular code') } }
class Human { constructor(name) {this.name = name} @deprecate useAngular() {
console.log('writing angular code') } } siddharth.writeAngular() // speak@Human: this feature will be deprecated soon! // writing angular code
class Human { constructor(name) {this.name = name} @deprecate('will be deprecated
in v2.0.0') useAngular() { console.log('writing angular code') } } siddharth.writeAngular() // speak@Human: will be deprecated in v2.0.0 // writing angular code
syntax @decorator = function const decorator = (target, key, descriptor)
=> { } @decorator(argument) = higher order function const decorator = (argument) => { return (target, key, descriptor) => { } }
syntax @decorator = function const decorator = (target, key, descriptor)
=> { } @decorator(argument) = higher order function const decorator = argument => (target, key, descriptor) => { }
@deprecate = function const deprecate = (target, key, descriptor) =>
{ const original = descriptor.value const name = `${target.constructor.name}.${key}` const message = 'this feature will be deprecated soon!' descriptor.value = () => { console.log(`${name} : ${message}`) original.apply(this, arguments) } return descriptor }
@deprecate(message) = higher order function const deprecate = message =>
(target, key, descriptor) => { const original = descriptor.value const name = `${target.constructor.name}.${key}` const message = 'this feature will be deprecated soon!' descriptor.value = () => { console.log(`${name} : ${message}`) original.apply(this, arguments) } return descriptor }
@deprecate(message) = higher order function const deprecate = message =>
(target, key, descriptor) => { const original = descriptor.value const name = `${target.constructor.name}.${key}` message = message || 'this feature will be deprecated soon!' descriptor.value = () => { console.log(`${name} : ${message}`) original.apply(this, arguments) } return descriptor }
don’t fret
jayphelps/core-decorators npm install core-decorators --save
import {readonly} from 'core-decorators' class Human { constructor(name) { this.name
= name } @readonly speak() { console.log('Hi! My name is ' + this.name) } } core-decorators
import {time} from 'core-decorators' class Human { constructor(name) { this.name
= name } @time('speak') // Human.speak-0: 1.582ms speak() { console.log('Hi! My name is ' + this.name) } } core-decorators
class decorators class method decorators ES7 decorators
@class-decorator class className { func() {} } class decorators
@type('mammal') class Human { constructor(name) { this.name = name console.log('I
am' + this.name + ', a ' + this.type) } } /* class Dolphin class Crocodile class Fish */ class decorators
@type('mammal') class Human { constructor(name) { this.name = name console.log('I
am' + this.name + ', a ' + this.type) } } const type = value => target => { // add {type: value} to the target class } class decorators
None
HOC: design pattern higher order components
A higher-order component is a function that takes a component
and returns a new (modified) component. class Label extends React.Component
HOC = class decorators
class Title extends React.Component { render () { return <div>hello
{this.props.name}</div> } }
class Title extends React.Component { render () { return <div>hello
{this.props.name}</div> } } /* <Post> <Title name="..."/> </Post> /*
@loading('name') class Title extends React.Component { render () { return
<div>hello {this.props.name}</div> } } /* <Post> <Title name="..."/> </Post> /* HOC
@loading('name') class Title extends React.Component { render () { return
<div>hello {this.props.name}</div> } } const loading = key => target => class extends React.Component { } HOC
@loading('name') class Title extends React.Component { render () { return
<div>hello {this.props.name}</div> } } const loading = key => Component => class extends React.Component { } HOC
@loading('name') class Title extends React.Component { render () { return
<div>hello {this.props.name}</div> } } const loading = key => Component => class extends React.Component { render () { if (this.props[key]) return <Component {...this.props} else return <div>loading...</div> } } HOC
https://github.com/acdlite/recompose npm install recompose --save
import {withProps} from 'recompose' recompose
import {withProps} from 'recompose' @withProps({name: 'world'}) class Title extends React.Component
{ render () { return <div>hello {this.props.name}</div> } } recompose
import {withHandlers, compose} from 'recompose' const handlers = withHandlers({ onClick:
props => event => mixpanel.track('Clicked', props) }) recompose
import {withHandlers, compose} from 'recompose' const handlers = withHandlers({ onClick:
props => event => mixpanel.track('Clicked', props) }) const analytics = compose(handlers) recompose
import {withHandlers, compose} from 'recompose' const handlers = withHandlers({ onClick:
props => event => mixpanel.track('Clicked', props) }) const analytics = compose(handlers) @analytics class Title extends React.Component { render () { return <div>hello {this.props.label}</div> } } recompose
import {onlyUpdateForKeys} from 'recompose' @onlyUpdateForKeys(['name']) class Title extends React.Component {
render () { return <div>hello {this.props.name}</div> } } /* <Post> <Title {...props}/> </Post> /* recompose
class Title extends React.Component { constructor () {} /* javascript
constructor */ css () {} /* css constructor ? */ render () { return <div>hello {this.props.name}</div> } } rant/wish
None
https://github.com/siddharthkp/css-constructor npm install css-constructor --save
import css from 'css-constructor' class Title extends React.Component { constructor
() {} @css` font-size: 16px; color: {this.props.colors}; &:hover {color: #FFF;} @media {max-width: 480px} {&: font-size: 18px;} ` render () { return <div>hello {this.props.name}</div> } } css-constructor
@css(styles) = higher order function const css = styles =>
(target, key, descriptor) => { } css-constructor
@css(styles) = higher order function const css = styles =>
(target, key, descriptor) => { const prettyCSS = process(styles) // fill props, media queries, etc. const cssClass = getUniqueClassName(prettyCSS) document.head.styles += {cssClass: prettyCSS} return componentWithClassName(cssClass) } css-constructor
Fin.
@siddharthkp