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
390
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
120
The life of CSS and it's future
siddharthkp
1
250
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
240
ES2015 on production? Not so fast
siddharthkp
1
370
Building node modules
siddharthkp
2
530
Other Decks in Technology
See All in Technology
Kiro入門|仕様駆動開発で変わるAI時代の開発スタイル
cmkudo
0
270
老害フォレンジッカーはAI羊の夢を見るか?
tadmaddad
0
360
関東Kaggler会発表資料
takoi
1
270
自宅NWにISR4331を導入してみた話
okaits
0
120
国家プロジェクトを支える「さくらONE」 大規模LLM開発におけるGPU障害を乗り越えるクラスター運用戦略
gpuunite_official
0
170
도구에서 동료까지: 10년차 AI 스타트업의 AI 적응기
inureyes
PRO
1
300
私がブラウザを自作したくなった理由
supurazako
1
280
LanceDB入門
mocobeta
9
640
【GCC2026】TrueHDRIを用いたルックデブ環境とライティングテクニック
bandainamcostudios
PRO
0
130
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
24k
案件に一番詳しいAIを Amazon Bedrock AgentCore で作る ― 知見が知見を生むチームへ / Compounding Knowledge with AgentCore
yusukeshimizu
1
160
MIXIで活躍できるエンジニアを 若手社員目線で考えてみる
mixi_engineers
PRO
0
110
Featured
See All Featured
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
390
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
1.1k
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
210
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
エンジニアに許された特別な時間の終わり
watany
108
250k
The Anti-SEO Checklist Checklist. Pubcon Cyber Week
ryanjones
0
220
Designing for Timeless Needs
cassininazir
1
450
Building Adaptive Systems
keathley
44
3.2k
A Soul's Torment
seathinner
6
3.5k
The innovator’s Mindset - Leading Through an Era of Exponential Change - McGill University 2025
jdejongh
PRO
1
270
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
480
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