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
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
Master Dataグループ紹介資料
sansan33
PRO
1
4.8k
Bill One 開発エンジニア 紹介資料
sansan33
PRO
7
20k
AIに持続⼒を与える 判断の⻑期記憶設計
eiei114
1
350
tamachi.go 誕生の裏側
rymiyamoto
1
160
LLM Internals: 언어 모델의 계보와 알고리즘 진화 (2023~2026)
inureyes
PRO
1
780
AI-DLC実践録_フルサイクル開発への挑戦
miyuc
0
300
Go 1.27 の標準パッケージに uuid が入った!のでいろいろ喋る / go_127_std_go_uuid
convto
3
530
DatadogのBits Chatが開発組織にもたらしたもの / What Bits Chat Has Brought Us
sms_tech
1
290
強化学習「理論」入門
enakai00
3
3.6k
AIペネトレーションテスト・ セキュリティ検証「AgenticSec」紹介資料
laysakura
2
9.3k
会社紹介資料 / Sansan Company Profile
sansan33
PRO
24
430k
FPGAが実現する遠方宇宙の高空間分解能天体撮影 -大型地上望遠鏡の視力を補正する「補償光学」とは?-
komei_mt
0
560
Featured
See All Featured
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
The Pragmatic Product Professional
lauravandoore
37
7.4k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
11
990
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.1k
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
350
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
370
Intergalactic Javascript Robots from Outer Space
tanoku
273
27k
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
490
GraphQLとの向き合い方2022年版
quramy
50
15k
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
370
Thoughts on Productivity
jonyablonski
76
5.3k
The untapped power of vector embeddings
frankvandijk
2
1.8k
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