Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
React.js v0.13 changes and beyond
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
koba04
March 30, 2015
Programming
19k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
React.js v0.13 changes and beyond
Gunosy React Meetup
http://gunosy-frontend.connpass.com/event/12636/
koba04
March 30, 2015
More Decks by koba04
See All by koba04
フロントエンドの現在地とこれから
koba04
10
5.4k
Standing on the shoulders of giants
koba04
0
3.2k
React/Next によるアプリケーション開発のこれから
koba04
61
19k
フロントエンド刷新をプロジェクトとして進める際に気をつけていること
koba04
3
2.1k
How useEvent would change our applications
koba04
1
3.3k
kintoneフロントエンド刷新によるモノリスからの脱却とその先に目指す未来
koba04
3
16k
Make it Declarative with React
koba04
0
2k
Ready for React in 2019
koba04
2
1.8k
Algorithms in React
koba04
14
19k
Other Decks in Programming
See All in Programming
ActionController meets Protocol Buffers
sorah
0
520
コードで差別化できない時代の ソフトウェアエンジニアリング / Software Engineering in an Era Where Code Doesn’t Differentiate
kishida
2
180
Long Living Tokens, Die, Die, Die! (or: The One Ring is Banned in Modern)
sylph01
0
300
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
動作中のプログラムの中身をリアルタイムに覗く / Realtime Debugger for CSharp with Roslyn
prota
1
1.9k
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
610
Compiling a real-world CLI tool to native with Static Hermes
tmikov2023
0
120
HTML-in-Canvasで作る未来のWeb UI表現
clockmaker
5
5.1k
パスワード再設定メールのURLについて知っておこう
uyuki234
0
160
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
160
TechTown - Creating Composable Callables in Contemporary C++
rollbear
0
130
3回つくってわかった、 定期実行ジョブ基盤の本質情報
takai
0
460
Featured
See All Featured
Building AI with AI
inesmontani
PRO
1
1.3k
How to Think Like a Performance Engineer
csswizardry
28
2.9k
Producing Creativity
orderedlist
PRO
348
41k
Data-driven link building: lessons from a $708K investment (BrightonSEO talk)
szymonslowik
1
1.4k
How to build a perfect <img>
jonoalderson
1
6.1k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
For a Future-Friendly Web
brad_frost
184
10k
A Tale of Four Properties
chriscoyier
163
24k
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
Unsuck your backbone
ammeep
672
58k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
Optimising Largest Contentful Paint
csswizardry
37
4k
Transcript
3FBDUKTWDIBOHFTBOECFZPOE (VOPTZ3FBDU.FFUVQ !LPCB
!LPCB w 8FC"QQMJDBUJPO&OHJOFFS w IUUQLPCBDPN w Ұਓ3FBDUKT"EWFOU$BMFBOEBS w IUUQRJJUBDPNBEWFOUDBMFOEBSSFBDUKT
None
None
3FBDUKTW
http://facebook.github.io/react/blog/2015/03/10/react-v0.13.html
http://blog.koba04.com/post/2015/03/05/react-js-v013-changes/
&4$MBTTFT
&4$MBTTFT class Hello extends React.Component { constructor(props) { super(props); this.state
= { count: 0 }; } static get propTypes() { title: React.PropTypes.string.isRequired } onClick() { this.setState({ count: this.state.count + 1 }) } render() { return ( <div> <p>{this.props.title}</p> <button onClick={this.onClick.bind(this)}>click</button> <p>{this.state.count}</p> </div> ); } }
&4$MBTTFT w HFU*OJUJBM4UBUFͰͳ͘ɺDPOTUSVDUPSͰTUBUFͷॳظΛࢦఆ w BVUPCJOEJOH͞Εͳ͘ͳͬͨ w NJYJOݱ࣌Ͱະαϙʔτ w IUUQTNFEJVNDPN!EBO@BCSBNPWNJYJOTBSFEFBEMPOHMJWFIJHIFS PSEFSDPNQPOFOUTBEGF
w HFU%0./PEFɺJT.PVOUFEɺSFQMBDF1SPQTɺ SFQMBDF4UBUFɺTFU1SPQTEFQSFDBUFE
1SPQJTJNNVUBCMF
1SPQJTJNNVUBCMF w 1SPQͷΛมߋ͠Α͏ͱ͢ΔͱXBSOJOH͕ग़ΔΑ͏ʹͳͬͨ w WͰ1SPQ͕*NNVUBCMFͰ͋Δ͜ͱΛલఏͱͨ͠ύϑΥʔϚ ϯεɾνϡʔχϯάΛ͢Δ͜ͱ͕త render() { // Warning:
Don't set .props.level of the React component. … var title = <title level={1} />; if (this.state.isImportant) title.props.level = 2; };
1SPQTJTJNNVUBCMF w TIPVME$PNQPOFOU6QEBUFͰมߋΛݕग़ग़དྷͳ͍ w UIJTQSPQTͱҾͰ͞ΕΔOFYU1SPQT͕ಉ͡ʹͳΔ w 3FBDUDSFBUF&MFNFOUҎޙมߋ͞Εͳ͍͜ͱΛอূ͍ͨ͠ w 1SPQ5ZQFTͷνΣοΫDSFBUF&MFNFOUͷ࣌ʹߦ͑Α͘ ͳΔ
w ωετͨ͠1SPQͷʹ͍ͭͯର֎ w ݅ʹΑͬͯ1SPQ͕ม͍͑ͨ߹ɺ3FBDUDSFBUF&MFNFOU ʹ͢1SPQΛ࡞Δ·Ͱʹ͍͍ͤ
1SPQJTJNNVUBCMF if (shouldUseFoo) { return <Foo foo={10} bar={true} />; }
else { return <Foo bar={false} />; } or var props = { bar: false }; if (shouldUseFoo) { props.foo = 10; props.bar = true; } return <Foo {...props} />;
TFU4UBUF
TFU4UBUFDBOUBLFBGVODUJPOBTTUBSHVNFOU w τϥϯβΫγϣϯ͕ඞཁͱ͞ΕΔσʔλͷߋ৽ʹ͏ w ͜Ε·Ͱ@QFOEJOH4UBUFΛ͏ඞཁ͕͋ͬͨ console.log(this.state.count) // 0 this.setState({count: this.state.count
+ 1}) this.setState({count: this.state.count + 1}) // state.count will render as 1 console.log(this.state.count) // 0 this.setState(function(state, props) { return {count: state.count + 1} }); this.setState(function(state, props) { return {count: state.count + 1} }); // state.count will render as 2
TFU4UBUFJTBMXBZTBTZODISPOPVT w ͜Ε·ͰॳճͷϚϯτ࣌ͷݺͼग़͠ಉظత͚ͩͬͨͲৗʹ ඇಉظͰ#BUDIVQEBUFʹͳΔ componentDidMount() { console.log(this.state.count) // 0 this.setState({
count: this.state.count + 1 }) this.setState({ count: this.state.count + 1 }) console.log(this.state.count) ɹ// v0.12 is 2 ɹ// v0.13 is 0 }
TFU4UBUFPOVONPVOUFEDPNQPOFOU w ΞϯϚϯτ͞ΕͨDPNQPOFOUͰͷTFU4UBUF GPSDF6QEBUF ͷݺͼग़ͨ࣌͠ʹΤϥʔͰͳ͘XBSOJOH͕ग़ྗ͞ΕΔΑ͏ʹ w "KBYʹର͢ΔϨεϙϯεΛTFU4UBUF͢ΔΑ͏ͳͱ͖ʹ JT.PVOUFEͰϒϩοΫ͢Δඞཁ͕ͳ͘ͳͬͨ request(‘/api/users/koba04’, (res)
=> { // if (this.isMounted()) { this.setState({ user: res.body.user }); // } });
3FBDUpOE%0./PEF
pOE%0./PEFJOTUFBEPGHFU%0./PEF w HFU%0./PEF&4$MBTTFTͰఏڙ͞Εͯͳ͍͠ DSFBUF$MBTTͰXBSOJOH͕ग़ΔͷͰஔ͖͑Δ class Sample extends React.Component { onClick()
{ this.setState({ // text: this.refs.inputText.getDOMNode().value text: React.findDOMNode(this.refs.inputText).value }); } render() { return( <div> <input type=“text” ref=“inputText” /> <button onClick={this.onClick.bind(this)}>click</button> </div> ); } }
0XOFSDPOUFYUUP1BSFOU$POUFYU
0XOFSBOE1BSFOU w 1BSFOUͱ0XOFS͕Ұக͠ͳ͍DPOUFYUΛ͓͏ͱ͢Δͱ XBSOJOH͕ग़ΔΑ͏ʹͳͬͨ w 1BSFOUϕʔεͷDPOUFYU·࣮ͩ͞Ε͍ͯͳ͍ w 0XOFS 1BSFOU DPOUFYU
w VOEPDVNFOUFEGFBUVSF
0XOFSBOE1BSFOU const p = <p>title</p>; class Hoge extends React.Component {
render() { return ( <div> {p} <span>hello</span> </div> ); } } span: owner is Hoge, parent is div ! Hoge p: owner is null, parent is div ! Hoge
$POUFYU const Parent React.createClass({ static get childContextTypes() { return {
name: React.PropTypes.string } } getChildContext() { return { name: ‘parent’ } } render() { return <Child /> } } // Child render <GrandChild /> class GrandChild extends React.Component { static get contextTypes() { return { name: React.PropTypes.string } } render() { <div>{this.context.name}</div> } }
$POUFYU const child = <Child />; const Parent React.createClass({ static
get childContextTypes() { return { name: React.PropTypes.string } } getChildContext() { return { name: ‘parent’ } } render() { return <div>{child}</div> } } class Child extends React.Component { static get contextTypes() { return { name: React.PropTypes.string } } render() { <div>{this.context.name}</div> } } React.render(<Parent />, document.getElementById(‘app’)); // Warning: owner-based and parent-based contexts differ
SFBDUSPVUFSXJUIDPOUFYU // 0.12.x var Foo = React.createClass({ mixins: [ Router.State
], render: function () { var id = this.getParams().id; // etc. ... } }); // 0.13.x w/ ES6 fanciness class Foo extends React.Component { render () { var { router } = this.context; var id = router.getCurrentParams().id; // etc. } } Foo.contextTypes = { router: React.PropTypes.func };
SFGDBOQBTTBDBMMCBDL class Hello extends React.Component { onClick() { this.setState({ text:
React.findDOMNode(this._inputText).value }); } render() { return ( <div> <input type=“text” ref={(c) => this._inputText = c} /> <button onClick={this.onClick.bind(this)}>click</button> </div> ); } } w طଘͷSFGlYYYzͦͷ··͑Δ 0XOFSDPOUFYU
3FBDUDMPOF&MFNFOU
3FBDUDMPOF&MFNFOU w 3FBDUBEEPOTDMPOF8JUI1SPQTʹ͍ۙ w 1SPQͱ*NNVUBCMFͱͯ͠ѻ͏͜ͱͰDMPOF͢Δ໘͕૿͑Δ ͨΊɺίΞͷ"1*ʹͳͬͨ w ҧ͍ͱͯ͠TUZMFDMBTT/BNFͷNFSHFߦΘΕͣɺSFG͕อ ࣋͞ΕΔ var
newChildren = React.Children.map( this.props.children, child => React.cloneElement(child, { foo: true }) );
DIJMESFO
4VQQPSUJUFSBUPSTBTDIJMESFO w JUFSBUPSΛͦͷ··͢͜ͱ͕ग़དྷΔ w *NNVUBCMFKTͷ-JTUΛNBQͨ͠ͷΛࠓ·ͰUP"SSBZͨ͠Γ ͢Δඞཁ͕͋ͬͨͷ͕ͦͷ··ͤΔ render() { <ul> {Immutable.List([1,2,3]).map(i
=> <li key={i}>{i}</li>)} </ul> }
,FZFE0CKFDU
,FZFE0CKFDU w \LFZFMFNFOU^ΛDIJMESFOʹ͢ͱXBSOJOH͕ग़ΔΑ͏ʹͳͬ ͨ w Ճ͞Εͨ3FBDUBEEPOTDSFBUF'SBHNFOUΛͬͨΓNBQͰ ճͨ͠Γ͢Ε͍͍ // Keyed Object
<div>{ {a: <span />, b: <span />} }</div> // === <div><span key=“a” /><span key=“b” /></div> <div>{React.addons.createFragment({a: <span />, b: <span />})</div>
+49
UBSHFUPQUJPO w EFGBVMUFTɻ͜Ε·Ͱͷڍಈʹ͢ΔͳΒFTΛࢦఆ͢Δ w FT͕EFGBVMUʹͳΓͦ͏ͳྲྀΕ͚ͩͬͨͲɺ!TFCNDL͕FT ΛEFGBVMUʹ͢ΔΑ͏ʹ͍࣋ͬͯͬͨ
UBSHFUPQUJPO w &4DMBTTFTͰॻ͍ͨ࣌ͷϝιου͕FOVNFSBCMF͔Ͳ͏͔ͷ ҧ͍͕͋Δ class Hello extends React.Component { foo()
{ console.log("foo"); } render() { return <div>hello</div>; } }
UBSHFUFT var ____Class0=React.Component;for(var ____Class0____Key in ____Class0) {if(____Class0.hasOwnProperty(____Class0____Key)) {Hello[____Class0____Key]=____Class0[____Class0____Key];}}var ____SuperProtoOf____Class0=____Class0===null? null:____Class0.prototype;Hello.prototype=Object.create(____SuperProtoOf____C
lass0);Hello.prototype.constructor=Hello;Hello.__superConstructor__=____Class 0;function Hello(){"use strict”;if(____Class0!==null) {____Class0.apply(this,arguments);}} Object.defineProperty(Hello.prototype,"foo", {writable:true,configurable:true,value:function() {"use strict"; console.log("foo"); }}); Object.defineProperty(Hello.prototype,"render", {writable:true,configurable:true,value:function() {"use strict"; return React.createElement("div", null, "hello"); }});
UBSHFUFT var ____Class0=React.Component;for(var ____Class0____Key in ____Class0) {if(____Class0.hasOwnProperty(____Class0____Key)) {Hello[____Class0____Key]=____Class0[____Class0____Key];}}var ____SuperProtoOf____Class0=____Class0===null? null:____Class0.prototype;Hello.prototype=Object.create(____SuperProtoOf____C
lass0);Hello.prototype.constructor=Hello;Hello.__superConstructor__=____Class 0;function Hello(){"use strict”;if(____Class0!==null) {____Class0.apply(this,arguments);}} Hello.prototype.foo=function() {"use strict"; console.log("foo"); }; Hello.prototype.render=function() {"use strict"; return React.createElement("div", null, "hello"); };
w ͱ^͕Ҏલจࣈྻͱͯ͠ѻΘΕ͍͚ͯͨͲQBSTFΤϥʔʹ ͳΔΑ͏ʹͳͬͨ BOE^BSFUSFBUFEBTBQBSTFFSSPS render() { return <div>10 > 2</div>;
// parse error! }
4IBMMPXSFOEFSJOH EPDVNFOUFE
4IBMMPXSFOEFSJOH w ֊·ͰΛSFOEFSͯ݁͠ՌΛฦ͢5FTU6UJMT w OPEFڥͰಈ࡞͢Δ w SFOEFSϝιουͷ݁ՌΛ֬ೝ͍ͨ͠ͱ͖ʹศར
4IBMMPXSFOEFSJOH class Parent extends React.Component { render() { return <div><Child
name=“child” /></div>; } } class Child extends React.Component { render() { return <div>{this.props.name}</div>; } } const shallowRenderer = React.addons.TestUtils.createRenderer(); shallowRenderer.render(<Parent />); const result = shallowRenderer.getRenderOutput(); console.assert(result.type === 'div'); console.assert(result.props.children.type === Child); console.assert(result.props.children.props.name === 'child'); console.assert(result.props.children.props.children === undefined); ➜ babel-node test.js ➜
3FBDUKTW 1MBO
3FVTF$POTUBOU7BMVF5ZQFT w ಉ͡3FBDU&MFNFOUΛ͍·Θ͢͜ͱͰEJ⒎ͷίετΛݮΒ͢ w SFOEFSԿݺΕͯͦͷʹ3FBDU&MFNFOU͕࡞ΒΕΔ function render() { return <div
className="foo" />; } // ͜͏ͬͯίϯύΠϧ͢Δ(Πϝʔδ) var div = React.createElement("div", {className: “foo”}); function render() { return div; }
5BHHJOH3FBDU&MFNFOUT w 3FBDU&MFNFOUʹUBH͚Λͯ͠ɺEJ⒎ΞϧΰϦζϜΛ࠷దԽ͢ Δ <div className="foo" style={{ width: w, height:
5 }}>{c}</div> // ͜͏ͬͯίϯύΠϧ͢Δ(Πϝʔδ) { __t: 7, type: 'div', props: { className: 'foo', style: { width: w, height: 5 }, children: c } } // ·ͨ var t = { className: 1, style: { height: 1 } }; { __t: t, type: 'div', props: { className: 'foo', style: { width: w, height: 5 }, children: c } }
*OMJOF3FBDU&MFNFOUT w QSPEVDUJPOϏϧυͷ͚࣌ͩɺ3FBDUDSFBUF&MFNFOUͰͳ͘ ͯJOMJOFPCKFDUʹม͢Δ͜ͱͰίετΛݮΒ͢ w DSFBUF&MFNFOU࣌ͷ1SPQ5ZQFTʹΑΔνΣοΫͰ͖ͳ͘ͳΔ ͷͰQSPEVDUJPOϏϧυͷ͚࣌ͩ <div className="foo">{bar}<Baz key="baz"
/></div> // ͜͏ͬͯίϯύΠϧ͢Δ(Πϝʔδ) { type: 'div', props: { className: 'foo', children: [ bar, { type: Baz, props: { }, key: 'baz', ref: null } ] }, key: null, ref: null }
None
3FBDUKTW
0CTFSWBCMF"1* w IUUQTHJUIVCDPNGBDFCPPLSFBDUJTTVFT class Foo { observe() { return {
user: loadUser(this.props.userID) }; } render() { if (this.data.user.id !== this.props.userID) { // Ensure that we never show inconsistent userID / user.name combinations. return <Spinner />; } return <div>Hello, {this.data.user.name} [{this.props.userID}]!</div>; } }
3FBDU—1BSTF w IUUQCMPHQBSTFDPNQBSTFBOESFBDUTIBSFEDIFNJTUSZ // Render a list of comments from
the Parse API var CommentBlock = React.createClass({ mixins: [ParseReact.Mixin], observe: function() { return { comments: (new Parse.Query('Comment')).descending('createdAt') }; }, render: function() { return <ul> {this.data.comments.map(function(c) { return <li>{c.text}</li> })} </ul>; } });
7FSTJPOJOH
7FSTJPOJOH w ݱࡏ w 9 ͰEFQSFDBUJPOXBSOJOHTɺ9 Ͱ"1*আ w Ҡߦ w
9:ͰEFQSFDBUJPOXBSOJOHTɺ9 Ͱ"1*আ w IUUQTHJTUHJUIVCDPN[QBPFFFGDFBG
3FBDUKTW
http://facebook.github.io/react/blog/2014/03/28/the-road-to-1.0.html
3FBDUKTW w ͢ͰʹQSPEVDUJPOSFBEZ w $POUFYUͲ͏͢Δ͔ w "EEPOTͷཧɾ֎෦ϥΠϒϥϦԽ w "OJNBUJPOͷվળ w
ʜ
5IBOLZPV TQFBLFSEFDLDPNLPCB