Upgrade to Pro — share decks privately, control downloads, hide ads and more …

React.js v0.13 changes and beyond

koba04
March 30, 2015

React.js v0.13 changes and beyond

koba04

March 30, 2015
Tweet

More Decks by koba04

Other Decks in Programming

Transcript

  1. 3FBDUKTWDIBOHFTBOECFZPOE
    (VOPTZ3FBDU.FFUVQ

    !LPCB

    View Slide

  2. !LPCB
    w 8FC"QQMJDBUJPO&OHJOFFS
    w IUUQLPCBDPN
    w Ұਓ3FBDUKT"EWFOU$BMFBOEBS
    w IUUQRJJUBDPNBEWFOUDBMFOEBSSFBDUKT

    View Slide

  3. View Slide

  4. View Slide

  5. 3FBDUKTW

    View Slide

  6. http://facebook.github.io/react/blog/2015/03/10/react-v0.13.html

    View Slide

  7. http://blog.koba04.com/post/2015/03/05/react-js-v013-changes/

    View Slide

  8. &4$MBTTFT

    View Slide

  9. &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 (

    {this.props.title}
    click
    {this.state.count}

    );
    }
    }

    View Slide

  10. &4$MBTTFT
    w HFU*OJUJBM4UBUFͰ͸ͳ͘ɺDPOTUSVDUPSͰTUBUFͷॳظ஋Λࢦఆ
    w BVUPCJOEJOH͞Εͳ͘ͳͬͨ
    w NJYJO͸ݱ࣌఺Ͱະαϙʔτ
    w [email protected]
    PSEFSDPNQPOFOUTBEGF
    w HFU%0./PEFɺJT.PVOUFEɺSFQMBDF1SPQTɺ
    SFQMBDF4UBUFɺTFU1SPQT͸EFQSFDBUFE

    View Slide

  11. 1SPQJTJNNVUBCMF

    View Slide

  12. 1SPQJTJNNVUBCMF
    w 1SPQͷ஋Λมߋ͠Α͏ͱ͢ΔͱXBSOJOH͕ग़ΔΑ͏ʹͳͬͨ
    w WͰ1SPQ͕*NNVUBCMFͰ͋Δ͜ͱΛલఏͱͨ͠ύϑΥʔϚ
    ϯεɾνϡʔχϯάΛ͢Δ͜ͱ͕໨త
    render() {
    // Warning: Don't set .props.level of the React component. …
    var title = ;
    if (this.state.isImportant) title.props.level = 2;
    };

    View Slide

  13. 1SPQTJTJNNVUBCMF
    w TIPVME$PNQPOFOU6QEBUFͰมߋΛݕग़ग़དྷͳ͍
    w UIJTQSPQTͱҾ਺Ͱ౉͞ΕΔOFYU1SPQT͕ಉ͡ʹͳΔ
    w 3FBDUDSFBUF&MFNFOUҎޙ͸มߋ͞Εͳ͍͜ͱΛอূ͍ͨ͠
    w 1SPQ5ZQFTͷνΣοΫ΋DSFBUF&MFNFOUͷ࣌ʹߦ͑͹Α͘
    ͳΔ
    w ωετͨ͠1SPQͷ஋ʹ͍ͭͯ͸ର৅֎
    w ৚݅ʹΑͬͯ1SPQ͕ม͍͑ͨ৔߹͸ɺ3FBDUDSFBUF&MFNFOU
    ʹ౉͢1SPQΛ࡞Δ·Ͱʹ౉ͤ͹͍͍

    View Slide

  14. 1SPQJTJNNVUBCMF
    if (shouldUseFoo) {
    return ;
    } else {
    return ;
    }
    or
    var props = { bar: false };
    if (shouldUseFoo) {
    props.foo = 10;
    props.bar = true;
    }
    return ;

    View Slide

  15. TFU4UBUF

    View Slide

  16. 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

    View Slide

  17. 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
    }

    View Slide

  18. 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 });
    // }
    });

    View Slide

  19. 3FBDUpOE%0./PEF

    View Slide

  20. 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(


    click

    );
    }
    }

    View Slide

  21. 0XOFSDPOUFYUUP1BSFOU$POUFYU

    View Slide

  22. 0XOFSBOE1BSFOU
    w 1BSFOUͱ0XOFS͕Ұக͠ͳ͍DPOUFYUΛ࢖͓͏ͱ͢Δͱ
    XBSOJOH͕ग़ΔΑ͏ʹͳͬͨ
    w 1BSFOUϕʔεͷDPOUFYU͸·࣮ͩ૷͞Ε͍ͯͳ͍
    w 0XOFS 1BSFOU DPOUFYU
    w VOEPDVNFOUFEGFBUVSF

    View Slide

  23. 0XOFSBOE1BSFOU
    const p = title;
    class Hoge extends React.Component {
    render() {
    return (

    {p}
    hello

    );
    }
    }
    span: owner is Hoge, parent is div ! Hoge
    p: owner is null, parent is div ! Hoge

    View Slide

  24. $POUFYU
    const Parent React.createClass({
    static get childContextTypes() {
    return { name: React.PropTypes.string }
    }
    getChildContext() { return { name: ‘parent’ } }
    render() { return }
    }
    // Child render
    class GrandChild extends React.Component {
    static get contextTypes() {
    return { name: React.PropTypes.string }
    }
    render() {
    {this.context.name}
    }
    }

    View Slide

  25. $POUFYU
    const child = ;
    const Parent React.createClass({
    static get childContextTypes() {
    return { name: React.PropTypes.string }
    }
    getChildContext() { return { name: ‘parent’ } }
    render() { return {child} }
    }
    class Child extends React.Component {
    static get contextTypes() {
    return { name: React.PropTypes.string }
    }
    render() {
    {this.context.name}
    }
    }
    React.render(, document.getElementById(‘app’));
    // Warning: owner-based and parent-based contexts differ

    View Slide

  26. 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
    };

    View Slide

  27. SFGDBOQBTTBDBMMCBDL
    class Hello extends React.Component {
    onClick() {
    this.setState({
    text: React.findDOMNode(this._inputText).value
    });
    }
    render() {
    return (

    this._inputText = c} />
    click

    );
    }
    }
    w طଘͷSFGlYYYz΋ͦͷ··࢖͑Δ 0XOFSDPOUFYU

    View Slide

  28. 3FBDUDMPOF&MFNFOU

    View Slide

  29. 3FBDUDMPOF&MFNFOU
    w 3FBDUBEEPOTDMPOF8JUI1SPQTʹ͍ۙ
    w 1SPQͱ*NNVUBCMFͱͯ͠ѻ͏͜ͱͰDMPOF͢Δ৔໘͕૿͑Δ
    ͨΊɺίΞͷ"1*ʹͳͬͨ
    w ҧ͍ͱͯ͠͸TUZMF΍DMBTT/BNFͷNFSHF͸ߦΘΕͣɺSFG͕อ
    ࣋͞ΕΔ
    var newChildren = React.Children.map(
    this.props.children,
    child => React.cloneElement(child, { foo: true })
    );

    View Slide

  30. DIJMESFO

    View Slide

  31. 4VQQPSUJUFSBUPSTBTDIJMESFO
    w JUFSBUPSΛͦͷ··౉͢͜ͱ͕ग़དྷΔ
    w *NNVUBCMFKTͷ-JTUΛNBQͨ͠΋ͷΛࠓ·Ͱ͸UP"SSBZͨ͠Γ
    ͢Δඞཁ͕͋ͬͨͷ͕ͦͷ··౉ͤΔ
    render() {

    {Immutable.List([1,2,3]).map(i => {i})}

    }

    View Slide

  32. ,FZFE0CKFDU

    View Slide

  33. ,FZFE0CKFDU
    w \LFZFMFNFOU^ΛDIJMESFOʹ౉͢ͱXBSOJOH͕ग़ΔΑ͏ʹͳͬ
    ͨ
    w ௥Ճ͞Εͨ3FBDUBEEPOTDSFBUF'SBHNFOUΛ࢖ͬͨΓNBQͰ
    ճͨ͠Γ͢Ε͹͍͍
    // Keyed Object
    { {a: , b: } }
    // ===
    {React.addons.createFragment({a: , b: })

    View Slide

  34. +49

    View Slide

  35. UBSHFUPQUJPO
    w EFGBVMU͸FTɻ͜Ε·Ͱͷڍಈʹ͢ΔͳΒFTΛࢦఆ͢Δ
    w FT͕EFGBVMUʹͳΓͦ͏ͳྲྀΕ͚ͩͬͨͲɺ!TFCNDL͕FT
    ΛEFGBVMUʹ͢ΔΑ͏ʹ͍࣋ͬͯͬͨ

    View Slide

  36. UBSHFUPQUJPO
    w &4DMBTTFTͰॻ͍ͨ࣌ͷϝιου͕FOVNFSBCMF͔Ͳ͏͔ͷ
    ҧ͍͕͋Δ
    class Hello extends React.Component {
    foo() {
    console.log("foo");
    }
    render() {
    return hello;
    }
    }

    View Slide

  37. 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");
    }});

    View Slide

  38. 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");
    };

    View Slide

  39. w ͱ^͕Ҏલ͸จࣈྻͱͯ͠ѻΘΕ͍͚ͯͨͲQBSTFΤϥʔʹ
    ͳΔΑ͏ʹͳͬͨ
    BOE^BSFUSFBUFEBTBQBSTFFSSPS
    render() {
    return 10 > 2; // parse error!
    }

    View Slide

  40. 4IBMMPXSFOEFSJOH EPDVNFOUFE

    View Slide

  41. 4IBMMPXSFOEFSJOH
    w ֊૚·ͰΛSFOEFSͯ݁͠ՌΛฦ͢5FTU6UJMT
    w OPEF؀ڥͰ΋ಈ࡞͢Δ
    w SFOEFSϝιουͷ݁ՌΛ֬ೝ͍ͨ͠ͱ͖ʹศར

    View Slide

  42. 4IBMMPXSFOEFSJOH
    class Parent extends React.Component {
    render() {
    return ;
    }
    }
    class Child extends React.Component {
    render() {
    return {this.props.name};
    }
    }
    const shallowRenderer = React.addons.TestUtils.createRenderer();
    shallowRenderer.render();
    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

    View Slide

  43. 3FBDUKTW 1MBO

    View Slide

  44. 3FVTF$POTUBOU7BMVF5ZQFT
    w ಉ͡3FBDU&MFNFOUΛ࢖͍·Θ͢͜ͱͰEJ⒎ͷίετΛݮΒ͢
    w SFOEFS͸Կ౓΋ݺ͹Εͯͦͷ౓ʹ3FBDU&MFNFOU͕࡞ΒΕΔ
    function render() {
    return ;
    }
    // ͜͏΍ͬͯίϯύΠϧ͢Δ(Πϝʔδ)
    var div = React.createElement("div", {className: “foo”});
    function render() {
    return div;
    }

    View Slide

  45. 5BHHJOH3FBDU&MFNFOUT
    w 3FBDU&MFNFOUʹUBH෇͚Λͯ͠ɺEJ⒎ΞϧΰϦζϜΛ࠷దԽ͢
    Δ
    {c}
    // ͜͏΍ͬͯίϯύΠϧ͢Δ(Πϝʔδ)
    { __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 } }

    View Slide

  46. *OMJOF3FBDU&MFNFOUT
    w QSPEVDUJPOϏϧυͷ͚࣌ͩɺ3FBDUDSFBUF&MFNFOUͰ͸ͳ͘
    ͯJOMJOFPCKFDUʹม׵͢Δ͜ͱͰίετΛݮΒ͢
    w DSFBUF&MFNFOU࣌ͷ1SPQ5ZQFTʹΑΔνΣοΫ͸Ͱ͖ͳ͘ͳΔ
    ͷͰQSPEVDUJPOϏϧυͷ͚࣌ͩ
    {bar}
    // ͜͏΍ͬͯίϯύΠϧ͢Δ(Πϝʔδ)
    { type: 'div', props: { className: 'foo', children:
    [ bar, { type: Baz, props: { }, key: 'baz', ref: null } ]
    }, key: null, ref: null }

    View Slide

  47. View Slide

  48. 3FBDUKTW

    View Slide

  49. 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 ;
    }
    return Hello, {this.data.user.name} [{this.props.userID}]!;
    }
    }

    View Slide

  50. 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
    {this.data.comments.map(function(c) {
    return {c.text}
    })}
    ;
    }
    });

    View Slide

  51. 7FSTJPOJOH

    View Slide

  52. 7FSTJPOJOH
    w ݱࡏ
    w 9ͰEFQSFDBUJPOXBSOJOHTɺ9Ͱ"1*࡟আ
    w Ҡߦ
    w 9:ͰEFQSFDBUJPOXBSOJOHTɺ9Ͱ"1*࡟আ
    w IUUQTHJTUHJUIVCDPN[QBPFFFGDFBG

    View Slide

  53. 3FBDUKTW

    View Slide

  54. http://facebook.github.io/react/blog/2014/03/28/the-road-to-1.0.html

    View Slide

  55. 3FBDUKTW
    w ͢ͰʹQSPEVDUJPOSFBEZ
    w $POUFYUͲ͏͢Δ͔
    w "EEPOTͷ੔ཧɾ֎෦ϥΠϒϥϦԽ
    w "OJNBUJPOͷվળ
    w ʜ

    View Slide

  56. 5IBOLZPV
    TQFBLFSEFDLDPNLPCB

    View Slide