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
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
270
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
220
A portal to the future
siddharthkp
7
2.9k
Do you even jam bruh?
siddharthkp
1
190
Designing in React
siddharthkp
0
220
ES2015 on production? Not so fast
siddharthkp
1
360
Building node modules
siddharthkp
2
520
Other Decks in Technology
See All in Technology
Claude Code×Terraform IaC テンプレート駆動開発
itouhi
1
490
Android の公式 Skill / Android skills
yanzm
0
120
2026.06.13_AI時代に事業会社が「SIer出身エンジニア」を求める理由 / Why Businesses Seek Engineers with a System Integrator Background in the AI Era
jumtech
0
1k
protovalidate-es を導入してみた
bengo4com
0
170
2026TECHFRESH畢業分享會 - 葬送的通靈師:化系統與用戶雜訊成行動訊號
line_developers_tw
PRO
0
740
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
1.9k
2026TECHFRESH畢業分享會 - Lightning Talk - E起 See See : 電商推薦讀心術? 數據說了算
line_developers_tw
PRO
0
740
Dario Amodi『Policy on the AI Exponential』を理解する
nagatsu
0
210
2026TECHFRESH畢業分享會 - Lightning Talk - 打造精準高效的 MCP 設計模式與測試實務
line_developers_tw
PRO
0
740
タクシーアプリ『GO』の実践的データ活用
mot_techtalk
3
190
Kubernetesにおける学習基盤とLLMOpsの概要
ry
1
240
「エンジニア進化論」2028年の開発完全自動化、エンジニアはどう進化するか
cyberagentdevelopers
PRO
4
4.4k
Featured
See All Featured
The SEO identity crisis: Don't let AI make you average
varn
0
490
WCS-LA-2024
lcolladotor
0
620
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
370
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.6k
Optimizing for Happiness
mojombo
378
71k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Docker and Python
trallard
47
3.9k
How to Build an AI Search Optimization Roadmap - Criteria and Steps to Take #SEOIRL
aleyda
1
2.1k
Ethics towards AI in product and experience design
skipperchong
2
310
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.4k
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