Slide 1

Slide 1 text

#VJMEJOH"QQTXJUI3FBDUKT'MVY ୈճ)5.-ͱ͔ษڧձ LPCB

Slide 2

Slide 2 text

LPCB w 8FC"QQMJDBUJPO&OHJOFFS w IUUQLPCBDPN w Ұਓ3FBDUKT"EWFOU$BMFOEBS w IUUQRJJUBDPNBEWFOUDBMFOEBSSFBDUKT

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

3FBDUKT w GBDFCPPL͕࡞ͬͨ+BWB4DSJQUͷ6*ϥΠϒϥϦ w +6455)&6* w 7*356"-%0. w %"5"'-08

Slide 5

Slide 5 text

6TJOH3FBDUKT w 'BDFCPPL w GBDFCPPLDPN NFTTFOHFSDPN JOTUBHSBNDPN w /FUqJY w ##$ w "UMBTTJBO w ʜ

Slide 6

Slide 6 text

8IZ3FBDUKT w ෳࡶͳϢʔβʔΠϯλʔϑΣΠεΛߏங͢ΔͨΊʹ w ։ൃޮ཰ͷ޲্Ͱ͸ͳͯ͘3FMJBCJMJUZ ৴པੑ Λ֬อ ͢Δ͜ͱ͕໨త

Slide 7

Slide 7 text

)FMMP import React from ‘react’; class Hello extends React.Component { render() { return
Hello {this.props.name}
; } } React.render( , document.getElementById(‘app’) ); //
Hello World

Slide 8

Slide 8 text

)FMMP import React from ‘react’; class Hello extends React.Component { render() { return
Hello {this.props.name}
; } } React.render( , document.getElementById(‘app’) ); //
Hello World
ʂʂʂʁʁʁ

Slide 9

Slide 9 text

+49 w 4ZOUBYTVHBSPG3FBDUDSFBUF&MFNFOU w +BWB4DSJQUͷදݱੑͱ5FNQMBUFͷΘ͔Γ΍͢͞ w 4FQBSBUJPOPGDPODFSOT
Hello
! React.createElement(“div”, {className: “foo”}, “Hello”) W͔Β ࠷దԽ΋

Slide 10

Slide 10 text

$PNQPOFOU w දࣔཁૉΛͦΕͧΕ$PNQPOFOUͱͯ͠෼ׂͦ͠ͷத ʹৼΔ෣͍ͱݟͨ໨Λ·ͱΊΔ w $PIFTJPO ڽू౓ ˢɺ$PVQMJOH ݁߹౓ ˣ

Slide 11

Slide 11 text

4UBUFMFTT w ֤$PNQPOFOUʹঢ়ଶΛ࣋ͨͤΔͷͰ͸ͳ͘ɺ਌ $PNQPOFOU͕ঢ়ଶΛ؅ཧ͢Δ w .VUBCMF มߋՄೳ ͳ஋͸ෳࡶੑΛੜΉ

Slide 12

Slide 12 text

-JLF4FSWFSTJEFSFOEFSJOH w ঢ়ଶ͕มΘͬͨΒ਌ͷ$PNQPOFOU͔Βશͯͷ $PNQPOFOUΛ࠶౓࡞Γ௚͢ w 1FSGPSNBODF ˠࠩ෼͚ͩΛ%0.ʹ൓ө

Slide 13

Slide 13 text

ᶃUSJHHFS ᶄFWFOU ᶅVQEBUF ᶆEBUB ᶇVQEBUF%0.

Slide 14

Slide 14 text

%PPNFOHJOF IUUQXXXTMJEFTIBSFOFUqPZEPQIPOFSFBDUQSFTPW

Slide 15

Slide 15 text

1SPQ4UBUF

Slide 16

Slide 16 text

1SPQ4UBUF w 1SPQ w $PNQPOFOUͷ*OUFSGBDF w *NNVUBCMF w 4UBUF w $PNQPOFOU͕0XOFSTIJQΛ࣋ͭ஋ w ࢠʹ1SPQͱͯ͠౉͢

Slide 17

Slide 17 text

1SPQ EBUB 1SPQ EBUB 1SPQ FWFOU ᶃUSJHHFS ᶅVQEBUF4UBUF 1SPQ FWFOU

Slide 18

Slide 18 text

ਆࢿྉ IUUQTTQFBLFSEFDLDPNIPLBDDIBJOUSPEVDUJPOUPSFBDU

Slide 19

Slide 19 text

-FU`TTUBSU

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

$PNQPOFOU

Slide 22

Slide 22 text

App InputFilter HNStory HNStories

Slide 23

Slide 23 text

$PNQPOFOU*'

Slide 24

Slide 24 text

class App extends React.Component { constructor(props) { super(props); this.state = { stories: [], filterText: ‘’}; } static get propTypes() { return { count: React.PropTypes.number } } static getDefaultProps() { return { count: 50 } } handleFilter(input) {} render() { return (

HackerNews Stories

); } } QBTTBTQSPQT IBTBTUBUF SFDFJWFQSPQT

Slide 25

Slide 25 text

class InputFilter extends React.Component { static get propTypes() { return { handleFilter: React.PropTypes.func.isRequired } } onInput(e) { this.props.handleFilter(e.target.value); } render() { return (
) } } MJTUFOUIFDIBOHFFWFOU EFMFHBUFUIFFWFOU

Slide 26

Slide 26 text

class HNStories extends React.Component { static get propTypes() { return { stories: React.PropTypes.arrayOf(React.PropTypes.object).isRequired } } render() { return (
{this.props.stories.map( story => )}
); } } QBTTBTQSPQT

Slide 27

Slide 27 text

class HNStory extends React.Component { static get propTypes() { return { story: React.PropTypes.object.isRequired } } render() { const {rank, url, title, by, kids} = this.props.story; const commentCount = kids ? kids.length : 0; return (
{rank}
{title}
by {by} {commentCount}comments link
); } }

Slide 28

Slide 28 text

React.render(, document.getElementById('app'));

Slide 29

Slide 29 text

6QEBUF4UBUF

Slide 30

Slide 30 text

class App extends React.Component { : componentDidMount() { fetch(HN_TOP_STORY_URL) .then(res => res.json()) .then(ids => { ids.slice(0, this.props.count).forEach((id, index) => { fetch(`${HN_STORY_URL}/${id}.json`) .then(res => res.json()) .then(story => { story.rank = index + 1; this.setState({ stories: this.state.stories.concat([story]).sort((a,b) => a.rank - b.rank) }); }) }) }); } }

Slide 31

Slide 31 text

class App extends React.Component { : handleFilter(input) { this.setState({filterText: input}); } filterStories() { const filterText = this.state.filterText.toLowerCase(); return this.state.stories.filter(story => { return !filterText || story.title.toLowerCase().indexOf(filterText) !== -1 || story.by.toLowerCase().indexOf(filterText) !== -1 ; }); } render() { return (

HackerNews Stories

); } }

Slide 32

Slide 32 text

class InputFilter extends React.Component { static get propTypes() { return { handleFilter: React.PropTypes.func.isRequired } } onInput(e) { this.props.handleFilter(e.target.value); } render() { return (
) } }

Slide 33

Slide 33 text

HJUIVCDPNLPCBSFBDUIBDLFSOFXTTUPSJFT

Slide 34

Slide 34 text

$PNQMFY"QQMJDBUJPO

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

IUUQTUXJUUFSDPNU@XBEBTUBUVT

Slide 37

Slide 37 text

'MVY IUUQTHJUIVCDPNGBDFCPPLqVY

Slide 38

Slide 38 text

'MVY w "SDIJUFDUVSF w 6OJEJSFDUJPOBM%BUBqPX w $PNQPOFOU"DUJPO$SFBUPS%JTQBUDIFS 4UPSF$PNQPOFOU

Slide 39

Slide 39 text

$PNQPOFOU "DUJPO$SFBUPST "DUJPO$SFBUPST %JTQBUDIFS 4UPSF 4UPSF $PNQPOFOU $PNQPOFOU 0UIFST )551ʜ .FUIPE "DUJPO "DUJPO &WFOU EBUB

Slide 40

Slide 40 text

App InputFilter HNStory HNStories

Slide 41

Slide 41 text

-FU`THPUPBqVYUSJQ

Slide 42

Slide 42 text

$PNQPOFOU

Slide 43

Slide 43 text

class App extends React.Component { constructor(props) { super(props); this.state = {stories: HNStoriesStore.filteredStrories()}; this._onChange = this._onChange.bind(this); } static get propTypes() { return { count: React.PropTypes.number}} static getDefaultProps() { return {count: 50} } componentDidMount() { HNStoriesStore.addChangeListener(this._onChange); AppHNStoriesActionCreators.fetch(this.props.count); } componentWillUnmount() { HNStoriesStore.removeChangeListener(this._onChange); } _onChange() { this.setState({ stories: HNStoriesStore.filteredStrories()}); } render() { return (

HackerNews Stories

) } } "DUJPO$SFBUPSΛݺͿ

Slide 44

Slide 44 text

class InputFilter extends React.Component { onInput(e) { AppHNStoriesActionCreators.filter(e.target.value); } render() { return (
) } } "DUJPO$SFBUPSΛݺͿ

Slide 45

Slide 45 text

"DUJPO$SFBUPST

Slide 46

Slide 46 text

const Action = { fetch(count) { fetch(HN_TOP_STORY_URL) .then(res => res.json()) .then(ids => { ids.slice(0, count).forEach((id, index) => { fetch(`${HN_STORY_URL}/${id}.json`) .then(res => res.json()) .then(story => { story.rank = index + 1; AppDispatcher.dispatch({ type: ActionTypes.RECEIVE_STORY, story: story }); }) }) }); }, filter(text) { AppDispatcher.dispatch({ type: ActionTypes.RECEIVE_FILTER_TEXT, text: text }); } }; "DUJPOΛൃߦͯ͠ %JTQBUDIFS΁

Slide 47

Slide 47 text

%JTQBUDIFS

Slide 48

Slide 48 text

import {Dispatcher} from 'flux'; const AppDispatcher = new Dispatcher(); શͯͷ"DUJPOΛड͚ͯ શͯͷ4UPSF΁ XBJU'PSͰॱ൪ͷ੍ޚ΋

Slide 49

Slide 49 text

4UPSF

Slide 50

Slide 50 text

const HNStories = assign({}, EventEmitter.prototype, { : }); HNStories.dispatchToken = AppDispatcher.register(action => { switch (action.type) { case ActionTypes.RECEIVE_STORY: stories = stories.concat([action.story]); HNStories.emitChange(); break; case ActionTypes.RECEIVE_FILTER_TEXT: filterText = action.text.toLowerCase(); HNStories.emitChange(); break; } }); શͯͷ"DUJPOΛड͚ͯ ඞཁͳ΋ͷ͚ͩॲཧ͢Δ

Slide 51

Slide 51 text

let stories = []; let filterText = ''; const HNStories = assign({}, EventEmitter.prototype, { emitChange() { this.emit(CHANGE_EVENT); }, addChangeListener(callback) { this.on(CHANGE_EVENT, callback); }, removeChangeListener(callback) { this.removeListener(CHANGE_EVENT, callback); }, filteredStrories() { return stories.filter(story => { return !filterText || story.title.toLowerCase().indexOf(filterText) !== -1 || story.by.toLowerCase().indexOf(filterText) !== -1 ; }); } }); : : $PNQPOFOUʹର͢Δ &WFOUͱHFUUFS

Slide 52

Slide 52 text

$PNQPOFOU

Slide 53

Slide 53 text

class App extends React.Component { constructor(props) { super(props); this.state = {stories: HNStoriesStore.filteredStrories()}; this._onChange = this._onChange.bind(this); } static get propTypes() { return { count: React.PropTypes.number}} static getDefaultProps() { return {count: 50} } componentDidMount() { HNStoriesStore.addChangeListener(this._onChange); AppHNStoriesActionCreators.fetch(this.props.count); } componentWillUnmount() { HNStoriesStore.removeChangeListener(this._onChange); } _onChange() { this.setState({ stories: HNStoriesStore.filteredStrories()}); } render() { return (

HackerNews Stories

) } } 4UPSF͔ΒσʔλΛड͚औΓ &WFOUΛड͚ͯߋ৽

Slide 54

Slide 54 text

"DUJPO$SFBUPST %JTQBUDIFS 4UPSF $PNQPOFOU $PNQPOFOU FNJU FNJU MJTUFO MJTUFO EBUB EBUB

Slide 55

Slide 55 text

HJUIVCDPNLPCBSFBDUIBDLFSOFXTTUPSJFTUSFFqVY

Slide 56

Slide 56 text

'MVYDPNQBSJTPO w IUUQTHJUIVCDPNWPSPOJBOTLJqVYDPNQBSJTPO w 'BDFCPPL'MVY w 'MVYJCMFCZ:BIPP w 'MVNNPY w .BUFSJBM'MVY w 'MVYYPS

Slide 57

Slide 57 text

$PODMVTJPO w $PNQPOFOUʹΑΔΧϓηϧԽ w ਌͔Βࢠ΁ͷ໌֬ͳσʔλͷྲྀΕ w ෳࡶͳϢʔβʔΠϯλʔϑΣΠεͷ୯७Խ

Slide 58

Slide 58 text

5IBOLZPV TQFBLFSEFDLDPNLPCB