Slide 1

Slide 1 text

5IFTUBUFPG3FBDUKT IUNMKWPM !LPCB

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

w XJMMCFIFMEJO+VOF "3FBDUKTNFFUVQPSHBOJ[FS

Slide 4

Slide 4 text

3FBDU&VSPQFJO1BSJT✈

Slide 5

Slide 5 text

8IPVTFT3FBDUKT

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

*OTUBHSBN

Slide 8

Slide 8 text

/FUqJY

Slide 9

Slide 9 text

5XJUUFS NPCJMF

Slide 10

Slide 10 text

BJSCOC

Slide 11

Slide 11 text

VCFS

Slide 12

Slide 12 text

3FBDUKTJTBCBUUMFUFTUFEMJCSBSZ GBDFCPPLVTFT3FBDUPONBTUFSCSBODIBUGBDFCPPLDPN

Slide 13

Slide 13 text

5IFIJTUPSZPG3FBDUKT

Slide 14

Slide 14 text

2013 2014 2015 2016 Flux v0.13 ReactNative for iOS GraphQL Redux Relay React Native for Android v0.14 React Native for Windows v15.0.0 …

Slide 15

Slide 15 text

8IZ3FBDU

Slide 16

Slide 16 text

w *UIJOLUIFSFBTPONBOZQFPQMFVTF3FBDUJT/05B QFSGPSNBODF w 'PSQSFEJDUBCMF6*NBOBHFNFOUCZl%FDMBSBUJWFBOEQVSF $PNQPOFOUzBOEl&YQMJDJUEBUBqPXzXJUIMFTT QFSGPSNBODFEFHSBEBUJPO w 1SPWJEJOHFTDBQFIBUDIFT 8IZ3FBDU

Slide 17

Slide 17 text

$PNQPOFOU

Slide 18

Slide 18 text

w :PVDBODSFBUFNPTUDPNQPOFOUTBT4UBUFMFTT'VODUJPO $PNQPOFOUT 4'$ w 4'$EPFTO`UIBTBCBDLJOHJOTUBODF w /PTUBUF /PMJGFDZDMFNFUIPET /PSFGT w 1FSGPQUJNJTBUJPOTGPS4'$XJMMCFJOUIFGVUVSF 4UBUFMFTT'VODUJPO$PNQPOFOUT const Item = ({item}) => (
{item.name}×{item.count}
); //

Slide 19

Slide 19 text

%PZPVOFFETUBUFTPSMJGFDZDMF NFUIPETJOZPVSDPNQPOFOUT ↪︎&4$MBTTFT$PNQPOFOUT

Slide 20

Slide 20 text

&4$MBTTFT class Counter extends React.Component { constructor(…args) {
 super(…args); this.state = { count: 0 }; this.onClick = this.onClick.bind(this); } onClick() { this.setState({ count: this.state.count + 1 }); } render() { return (
++
{this.state.count}
); }

Slide 21

Slide 21 text

w 4VQQPSUJOHNJOJNVN"1*T w *UEPFTO`UTVQQPSUSFQMBDF4UBUF JT.PVOUFE w .JYJOTBSFEFBE -POHMJWF)JHI0SEFS$PNQPOFOUT )0$ &4$MBTTFT$PNQPOFUT import shallowCompare from ‘react-addons-shallow-compare’; const pure = Component => class PureComponent extends React.Component { shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this, nextProps, nextState); } render () { return } }; const Item = ({item}) =>
{item.name}×{item.count}
; const PureItem = pure(Item);

Slide 22

Slide 22 text

w 3FBDUDSFBUF$MBTTGFFMTPVUEBUFE w *UIBTGFBUVSFTUIBUJTDPOWFOJFOUGPSEFWFMPQFST w NJYJOH‎)JHI0SEFS$PNQPOFOUT w BVUPCJOEJOH‎&4$MBTT'JFMET4UBUJD1SPQFSUJFT w *UNBZCFDPNFBTFQBSBUFQBDLBHF 3FBDUDSFBUF$MBTT class Button extends React.Component { onClick = () => this.setState({count: this.state.count + 1}); } Stage1

Slide 23

Slide 23 text

DPSFOPUFT.BZ

Slide 24

Slide 24 text

w "TJNQMFCFODINBSLGPS&4$MBTTFT XJUI TIPVME$PNQPOFOU6QEBUF WT4'$ w IUUQTKTpEEMFOFULPCBKNL &4$MBTTFTWT4'$

Slide 25

Slide 25 text

"EE3FBDU1VSF$PNQPOFOU JOIFSJUQVSJUZGPS GVODUJPOBMDPNQPOFOUT WIP PureComponent was merged as #7195. It’s a PureRenderMixin for ES Classes.

Slide 26

Slide 26 text

"EE3FBDU1VSF$PNQPOFOU JOIFSJUQVSJUZGPS GVODUJPOBMDPNQPOFOUT class Post extends React.PureComponent { // or React.Component render() { return (
); } } function PostHeader(props) { // ... } function PostBody(props) { // ... } Pure Pure This wasn’t merged

Slide 27

Slide 27 text

"QJUGBMMPGTIPVME$PNQPOFOU6QEBUF import shallowCompare from ‘react-addons-shallow-compare’; class Item extends React.Component { shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this, nextProps, nextState); } render() { return (

{this.props.name}

click
); } } console.log(‘click’)} />

Slide 28

Slide 28 text

SFBDUBEEPOTQFSG w 1FSGIBTSFXSJUUFOCZ%BO"CSBNPWBUW w QSJOU%0.SFOBNFEUPQSJOU0QFSBUJPOT w :PVDBO import Perf from ‘react-addons-perf’; Perf.start(); ReactDOM.render(, el); setTimeout(() => { ReactDOM.render(, el); Perf.stop(); Perf.printWasted(); }, 1000);

Slide 29

Slide 29 text

XIZEJEZPVVQEBUF w IUUQTHJUIVCDPNHBSCMFTXIZEJEZPVVQEBUF w zJGEFpOFB$PNQPOFOUIBTDPNQPOFOU%JE6QEBUF UIF XIZEJEZPVVQEBUFXJMMOPUXPSLz import React from ‘react’; import {whyDidYouUpdate} from 'why-did-you-update'; whyDidYouUpdate(React); // monkey patches for React

Slide 30

Slide 30 text

1SPQT

Slide 31

Slide 31 text

w 1SPQTJTJNNVUBCMF Wʙ w 0CKFDUGSFF[F!EFW Wʙ w "EEFE3FBDUDMPOF&MFNFOU Wʙ w TFU1SPQTBOESFQMBDF1SPQTIBWFHPOF W w 1SPQ5ZQFTJTBMFHBDZGFBUVSF w :PVDBOVTF'MPXPS5ZQF4DSJQUJOTUFBE JNDPNQBUJCMF w *UNBZCFDPNFBTFQBSBUFEQBDLBHF 1SPQT

Slide 32

Slide 32 text

DPSFOPUFT.BZ

Slide 33

Slide 33 text

4UBUF

Slide 34

Slide 34 text

w TFU4UBUFCFIBWFTBTCBUDIFE6QEBUFTJO&WFOU-JTUFOFS BOEMJGFDZDMFNFUIPET w :PVDBOQBTTBGVODUJPOUPTFU4UBUFGPSUSBOTBDUJPOBM VQEBUFT Wʙ 4UBUF onClick() { this.setState((state, props) => ({count: state.count + 1})); this.setState((state, props) => ({count: state.count + 1})); }

Slide 35

Slide 35 text

w UIFGPMMPXJOHFYBNQMF SFOEFSPDDVSTUXPUJNFT w /PCBUDIFE6QEBUFT "QJUGBMMPGCBUDIFE6QEBUFT onClick() { fetch(API_URL) .then(res => res.json()) .then(json => { this.setState({user: json.user}); // … this.setState({completed: true}); }); }

Slide 36

Slide 36 text

w 3FBDU%0.VOTUBCMF@CBUDIFE6QEBUFTQSPWJEFT CBUDIFE6QEBUFT:PVDBOBWPJEVOOFDFTTBSZSFOEFST w *U`TVOTUBCMF#VUUIF"1*JTVTFECZ3FMBZFUD VOTUBCMF@CBUDIFE6QEBUFT onClick() { fetch(API_URL) .then(res => res.json()) .then(json => { ReactDOM.unstable_batchedUpdates(() => { this.setState({user: json.user}); // … this.setState({completed: true}); }); }); }

Slide 37

Slide 37 text

3FBDU&MFNFOU

Slide 38

Slide 38 text

w 3FBDUDSFBUF&MFNFOUSFUVSOTQMBJOPCKFDU Wʙ w /PNPSFTQBOBOEEBUBSFBDUJE FYDFQU443 Wʙ 3FBDU&MFNFOU //
Hello {name}
Hello React
Hello React

Slide 39

Slide 39 text

3FG%0.

Slide 40

Slide 40 text

w 4USJOH3FGJTMFHBDZ:PVTIPVMEVTFDBMMCBDL3FG w %0.$PNQPOFOUTSFUVSOJUT%0./PEFBT3FG w HFU%0./PEFTIBTHPOF W w 3FBDU%0.pOE%0./PEFTSFUVSOTB%0./PEFGSPN $PNQPTJUF$PNQPOFOUT 3FG%0. render() { let text; return (
c && c.focus()} /> text = c} />
); }

Slide 41

Slide 41 text

$POUFYU

Slide 42

Slide 42 text

w $POUFYUCFDPNFTBEPDVNFOUFEGFBUVSF w IUUQGBDFCPPLHJUIVCJPSFBDUEPDTDPOUFYUIUNM w *U`TBGFBUVSFGPS3FBDUMJCSBSJFT $POUFYU const Item = ({item}, {settings}) => (
{item.name}
); Item.contextTypes = { settings: React.PropTypes.object };

Slide 43

Slide 43 text

5FTU

Slide 44

Slide 44 text

w 8FDBOHFU4IBMMPX3FOEFSFS W w :PVDBOUFTUGPS3FBDU$PNQPOFOUTPO/PEF FOWJSPONFOU w *UEPFTO`UTVQQPSU3FGBOEMJGFDZDMFNFUIPETDPNQMFUFMZ w *U`TBl4IBMMPXzSFOEFSJOH 5FTU const shallowRenderer = TestUtils.createRenderer(); const elementTree = shallowRenderer.render(); assert(elementTree.props.children[0].type === ‘div’);

Slide 45

Slide 45 text

w 5FTUJOHVUJMJUJFTGPS3FBDU$PNQPOFOUT w TIBMMPX NPVOU SFOEFS w :PVDBOUFTUGPS3FBDU$PNQPOFOUFBTJMZBOE NBJOUBJOBCMF BJSCOCFO[ZNF import {shallow} from ‘enzyme’; const wrapper = shallow(); assert(wrapper.find(Link).prop(‘to’) === ‘/foo’); wrapper.find(‘button’).simulate(‘click’);

Slide 46

Slide 46 text

w %PFT&O[ZNFCFDPNFUIFP⒏DJBM5FTU6UJMT BJSCOCFO[ZNF core-notes May 05.

Slide 47

Slide 47 text

&4-JOU3FBDU

Slide 48

Slide 48 text

w &4-JOUIFMQTZPVUPDSFBUF3FBDU$PNQPOFOUT w FTMJOUQMVHJOSFBDU w 3FBDUTQFDJpDMJOUJOHSVMFTGPS&4-JOU w IUUQTHJUIVCDPNZBOOJDLDSFTMJOUQMVHJOSFBDU w FTMJOUQMVHJOKTYBZ w 4UBUJD"45DIFDLFSGPSBDDFTTJCJMJUZSVMFTPO+49FMFNFOUT w IUUQTHJUIVCDPNFWDPIFOFTMJOUQMVHJOKTYBZ &4-JOU3FBDU

Slide 49

Slide 49 text

&4-JOU3FBDU

Slide 50

Slide 50 text

&4-JOU3FBDU w OPTUSJOHSFGT w QSFGFSFTDMBTT w QSFGFSTUBUFMFTTGVODUJPO w OPEJSFDUNVUBUJPOTUBUF w TPSUDPNQ w KTYOPCJOE w KTYLFZ

Slide 51

Slide 51 text

3FBDU/BUJWF

Slide 52

Slide 52 text

w 3FBDU/BUJWFIBTBIVHFFDPTZTUFN w 'BDFCPPLJTVTJOH3FBDU/BUJWFJO'BDFCPPLBQQ 3FBDU/BUJWF

Slide 53

Slide 53 text

3FBDU/BUJWF

Slide 54

Slide 54 text

w 3FBDU/BUJWFJTKVTUBSFOEFSFS 3FBDU/BUJWF import React, {Component} from 'react'; import {TabBarIOS, NavigatorIOS} from ‘react-native’; class App extends Component { render() { return ( ); } }

Slide 55

Slide 55 text

w 3FBDU/BUJWFJTKVTUBSFOEFSFS 3FBDU/BUJWF (facebook/react) src !"" isomorphic # !"" children # !"" classic # $"" modern !"" renderers # !"" art # !"" dom # # !"" client # # !"" server # # $"" shared # !"" native # !"" noop # $"" shared !"" shared

Slide 56

Slide 56 text

NBLFJUPQFODPN

Slide 57

Slide 57 text

"SDIJUFDUVSF

Slide 58

Slide 58 text

w IUUQTHJUIVCDPNSFBDUKTSFBDUCBTJD SFBDUCBTJT

Slide 59

Slide 59 text

w IUUQTHJUIVCDPNJBNEVTUBOUJOZSFBDUSFOEFSFS w "NJOJNVNJNQMFNFOUBUJPOPG3FBDU3FOEFSFS 5JOZ3FBDU3FOEFSFS

Slide 60

Slide 60 text

'VUVSF

Slide 61

Slide 61 text

w :PVTIPVMEXBUDISFBDUKTDPSFOPUFT w 3FBDUXJMMSFMFBTFOFXNJOPSPSQBUDIWFSTJPOTFWFSZUXP XFFLT w 5PBEPQU&NCFSMJLF3'$QSPDFTT w &YQFSJNFOUJOHXJUI4UZMF4IFFUDSFBUF POUIFXFC w /FX3FDPODJMFS w 3FBDU$PSFJTNPSFTJNQMFS 'VUVSF

Slide 62

Slide 62 text

<8*1>/FX$PSF"MHPSJUIN

Slide 63

Slide 63 text

/FX$PSF"MHPSJUIN

Slide 64

Slide 64 text

/FX3FDPODJMFS*OGSB

Slide 65

Slide 65 text

<'JCFS>$IJME3FDPODJMFS/FX$PSPVUJOFT 1SJNJUJWF

Slide 66

Slide 66 text

w 4DIFEVMJOH3FBDUSFDVSTJWFSFOEFSJOH w $VSSFOUMZ SFDVSTJWFSFOEFSJOHJTTZODISPOPVT XIJDIJTB SFBTPO3FBDUJTTMPX <8*1>/FX3FDPODJMFS // src/renderers/noop/ReactNoop.js var NoopRenderer = ReactFiberReconciler({ createHostInstance() { }, scheduleHighPriCallback(callback) { scheduledHighPriCallback = callback; }, scheduleLowPriCallback(callback) { scheduledLowPriCallback = callback; },

Slide 67

Slide 67 text

<8*1>/FX3FDPODJMFS function Continuation({ isSame }) { return {isSame ? 'foo==bar' : 'foo!=bar'}; } function Child({ bar }) { return ReactCoroutine.createYield({ bar: bar, }, Continuation, null); } function Indirection() { return [, ]; } function HandleYields(props, yields) { return yields.map(y => ); } function Parent(props) { return ReactCoroutine.createCoroutine( props.children, HandleYields, props ); } function App() { return
; } ReactNoop.render(); ReactNoop.flush();

Slide 68

Slide 68 text

<8*1>/FX3FDPODJMFS

Slide 69

Slide 69 text

<8*1>/FX3FDPODJMFS w 3FTPVSDFT w IUUQTHJUIVCDPNSFBDUKTSFBDUCBTJD w IUUQTHJUIVCDPNSFBDUKTSFBDUGVUVSFCMPCNBTUFS -BZPVUQSPUPUZQFJOEFYKT

Slide 70

Slide 70 text

5IBOLZPV TQFBLFSEFDLDPNLPCB