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
イカリング2におけるシングルページアプリケーション
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
cockscomb
October 02, 2017
Programming
7.7k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
イカリング2におけるシングルページアプリケーション
cockscomb
October 02, 2017
More Decks by cockscomb
See All by cockscomb
はてなアカウント基盤 State of the Union
cockscomb
1
1.4k
jq at the Shortcuts
cockscomb
1
2.1k
GraphQL放談
cockscomb
4
2.2k
GraphQL Highway
cockscomb
28
8.9k
吉田を支える技術
cockscomb
0
2.6k
コーポレートサイトを静的化してAmplify Consoleにデプロイする
cockscomb
0
3.5k
ユーザインターフェイスと非同期処理
cockscomb
5
2.1k
GUIアプリケーションの構造と設計
cockscomb
10
10k
あなたの知らない UIKit の世界 — UITableView に UITextView を置きたい
cockscomb
1
7.7k
Other Decks in Programming
See All in Programming
AWS DevOps Agentで インシデント対応をAIに任せたい
honmarkhunt
6
2.5k
週末にAI-DLCを本気で回したら$1,600溶けた
hbashimizu
0
130
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
4.3k
LoopHub - ローカルで動く GitHub で、AI と共同開発
jugyo
0
450
in-process GraphQL のすすめ #ginzajs
izumin5210
4
1.5k
RSSとCodexを使ってX投稿自動化してみた
ochtum
0
110
変化を抱擁するドキュメントの作り方 - ビジネスルール駆動開発がもたらす、コードとの新しい関係
ioki
2
120
レビュー履歴をAIに食わせて、 Compose移行を加速するs
shihochan
0
270
Seeing Through Serverless: Observability for AWS Lambda with ADOT and CloudWatch Application Signals
seike460
PRO
1
120
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
0
240
初めての模倣学習とVLA
natsutan
0
500
Vibes Containers 〜AIで変わるコンテナ設計と運用〜
tkikuc
2
500
Featured
See All Featured
Designing for humans not robots
tammielis
254
26k
Utilizing Notion as your number one productivity tool
mfonobong
4
570
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
230
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
670
Mobile First: as difficult as doing things right
swwweet
225
10k
Agile that works and the tools we love
rasmusluckow
331
22k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Writing Fast Ruby
sferik
630
63k
Information Architects: The Missing Link in Design Systems
soysaucechin
1
1.1k
Evolving SEO for Evolving Search Engines
ryanjones
0
280
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
490
30 Presentation Tips
portentint
PRO
1
390
Transcript
ΠΧϦϯάʹ͓͚Δ γϯάϧϖʔδΞϓϦέʔγϣϯ
id:cockscomb Ճ౻ਘथ גࣜձࣾͯͳ γχΞΞϓϦέʔγϣϯΤϯδχΞ ΠΧϦϯάͷ5FDI-FBE
/JOUFOEP
ΠΧϦϯά w /JOUFOEP4XJUDI0OMJOFΞϓϦ෦ͷαʔϏε w 4QMBUPPOͷϓϨΠσʔλΛݟΔ͜ͱ͕Ͱ͖Δ
࠾༻ٕज़ w ϑϩϯτΤϯυ41" w 5ZQF4DSJQU w 3FBDU 3FEVY w ཪଆʹΦʔέετϨʔγϣϯͱͯ͠ͷ"1*αʔόʔ
w 1FSM w %PDLFSͰಈ͍͍ͯΔ
લఏ w ͳΜͰͰ͖ΔνʔϜ w 8FCΞϓϦέʔγϣϯ w J04"OESPJEͷωΠςΟϒΞϓϦ w 41"ॳΊͯ w
σβΠφʔ͕3FBDU$PNQPOFOUΛ৮ΕΔ
w ٕज़બఆ w 3FBDUͱ3FEVYʹΑΔεςʔτϑϧΞϓϦέʔγϣϯ w 3FEVY4BHB w 8FCϖʔδͱͯ͠ͷ41"
ٕज़બఆ
41"ʹ͢Δཧ༝ w /JOUFOEP4XJUDI0OMJOFΞϓϦͷαʔϏε w ΞϓϦʹظ͞ΕΔϦονͳମݧ w J04"OESPJEͷ8FC7JFXͰදࣔͰ͖ΕΑ͍
41"ʹ͢Δཧ༝ w αʔϏεͷಛੑ w ࠶๚͕ଟ͍ ˠΫϥΠΞϯταΠυΩϟογϡͷޮՌ͕ߴ͍ w 17ηογϣϯൺ͕େ͖͍ ˠॳճͷಡΈࠐΈΑΓͦͷޙͷମݧΛॏࢹ
Ұൠతʹ41"Λ࠾༻Ͱ͖Δ͔ w 41"ʹ͢ΔϢʔβʔϝϦοτͱ։ൃͷఱṝ w ఆ͞ΕΔར༻ύλʔϯ͕41"ʹϚον͢Δ͔ w ηογϣϯɺ17ηογϣϯ͕ଟ͚Ε૬ੑ͕͍͍ w ݕࡧ4/4͔ΒͷϏδλʔ͕ଟ͚ΕॳճͷಡΈࠐΈΛૣ͘͢Δ w
αϙʔτରͷϒϥβ w 4&0ͷॏཁੑ
࠷ޙ༐ؾ w ͍ͥͬͨʹࣗͰͳΜͱ͔͢Δܾҙ
3FBDUͱ3FEVYʹΑΔ εςʔτϑϧΞϓϦέʔγϣϯ
εςʔτϑϧΞϓϦέʔγϣϯ w )551ϦΫΤετʹରͯ͠)551ϨεϙϯεΛฦ͢ ˠεςʔτϨε w σʔλϕʔεͰӬଓԽ w ηογϣϯʹΑͬͯ࿈ଓੑΛอͭ w 41"(6*ΞϓϦέʔγϣϯ
ˠεςʔτϑϧ
Component Props Component Component Component Component Component Virtual DOM Virtual
DOM Virtual DOM Props Props 3FBDU w ΞϓϦέʔγϣϯ $PNQPOFOUͷू߹ମ w $PNQPOFOUೖྗΛݩʹ ৽ͨͳ$PNQPOFOUΛग़ྗ͢Δ ؔͱΈͳͤΔ w ࠷ऴతʹ%0.$PNQPOFOUΛ ग़ྗ͢Δ
σʔλϑϩʔ w 1SPQT ˠ֎෦͔Βͷೖྗ w 4UBUFT ˠ$PNQPOFOUͷঢ়ଶ w $POUFYU ˠࢠଙ$PNQPOFOUʹΘΔঢ়ଶ
࣌ࠁ import * as React from 'react'; interface TimeProps {
time: Date, } export const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; };
ͭͷ$PNQPOFOU w 4UBUFMFTT'VODUJPOBM$PNQPOFOU w 1VSF$PNQPOFOU w $PNQPOFOU
4UBUFMFTT'VODUJPOBM$PNQPOFOU w ؔ w ঢ়ଶΛ࣋ͨͳ͍ Component Props Component Component Props
1VSF$PNQPOFOU w Ϋϥε w ঢ়ଶΛ࣋ͭ w 4UBUFTJNNVUBCMFͳΦϒδΣΫτ Component Props Component
Component Props States
$PNQPOFOU w Ϋϥε w ঢ়ଶΛ࣋ͭ w 4UBUFTJNNVUBCMFͱݶΒͳ͍ Component Props Component
Component Props States
ͭͷ$PNQPOFOU w 4UBUFMFTT'VODUJPOBM$PNQPOFOU͕࠷୯७ w 1VSF$PNQPOFOUΛ͏͜ͱ͕ଟ͍
*NNVUBCMF w σʔλ͕JNNVUBCMFͰ͋Δํ͕߹͕͍͍ w ݹ͍ͱ৽͍͕͠ಉ͡ͳΒԿ͠ͳ͍͍ͯ͘ w *NNVUBCMFͳΦϒδΣΫτ===ͰൺֱͰ͖Δ
*NNVUBCMF w 0CKFDUBTTJHO const newObj = Object.assign({}, oldObj, { key:
value }) w 4QSFBE0QFSBUPS const newObj = { ...oldObj, key: value } w *NNVUBCMFKT
Store Reducer State Action dispatch subscribe 3FEVY w ୯Ұͷ4UPSFʹશͯͷঢ়ଶ w
TVCTDSJCFͰมԽΛݕͰ͖Δ w 0CTFSWFSύλʔϯ w ঢ়ଶΛม͍͑ͨͱ͖ 4UPSFʹ"DUJPOΛૹΔ w 3FEVDFS͕"DUJPOʹԠͯ͡ ঢ়ଶΛมߋ͢Δ
"DUJPOϝιουσΟεύον w "DUJPOϝιουͱύϥϝʔλΛ߹Θͤͨͷ w "DUJPO$SFBUPSͱݺΕΔϑΝΫτϦʔؔͰ࡞Δ w 3FEVDFS4UPSFΛมߋ͢ΔͨΊͷϨγʔό w DPNCJOF3FEVDFSTͰෳͷ3FEVDFSΛΈ߹Θͤͯ 4UPSFΛׂ౷࣏͢Δ
3FBDU3FEVY Component Component Component Component Virtual DOM Virtual DOM Virtual
DOM Props Props Component Component
3FBDU3FEVY Connected Provider Connected Component Component Component Component Virtual DOM
Virtual DOM Virtual DOM Props Props Component Component
3FBDU3FEVY w 1SPWJEFS͕DPOUFYUͰ4UPSFΛࢠଙ$PNQPOFOUʹఏڙ w DPOOFDUؔͰ$PNQPOFOUΛ4UPSFͱଓ w 4UPSFΛTVCTDSJCFͯ͠1SPQTʹม͢Δ w ΠϕϯτΛ"DUJPOͱͯ͠4UPSFʹ͑Δ w
ˠ%*
࣌ࠁ import * as React from 'react'; interface TimeProps {
time: Date, } export const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; };
࣌ࠁ import * as React from 'react'; import {connect} from
'react-redux'; interface TimeProps { time: Date, } const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; }; export default connect(state => ({ time: state.time }))(Time);
3FEVY w ΞϓϦέʔγϣϯશମͷঢ়ଶ w 0CTFSWFSύλʔϯͱ%* w 4UPSFͷઃܭ͕ॏཁ w 3FEVDFSͷΈ߹ΘͤͰׂ౷࣏ w
Կ͔3FEVYͷ4UPSFʹೖΕΔඞཁͳ͍
8FC"1*ͷϨεϙϯε w 3FEVYͷ4UPSFʹͲ͏อ࣋͢Δͷ͔ w ϦιʔεͷεςʔτϚγϯ w ະऔಘɾ௨৴தɾऔಘࡁΈɾऔಘࣦഊ w RemoteResource<T, E>
3FNPUF3FTPVSDF5 & empty pending resolved<T> failed<E> request succeeded failed reload
reload
3FNPUF3FTPVSDF5 & w latestValueͱͯ͠࠷ޙͷΛอ͓࣋ͯ͘͠ w Ϧϩʔυதʹ͕ফ͑ͳ͍ w औಘʹޭͨ࣌͠ࠁอ͓࣋ͯ͘͠ͱศར w ߴ֊ؔ
RemoteResource<T, E>.map<U>((T) -> U) -> RemoteResource<U, E>
3FNPUF3FTPVSDF5 & enum State { EMPTY = "empty", PENDING =
"pending", RESOLVED = "resolved", FAILED = "failed", } abstract class RemoteResource<T, E> { abstract state: State; abstract latestValue: T | null; abstract error: E | null; }
3FNPUF3FTPVSDF5 & w ݱࡏͷঢ়ଶʹΑΒͣ࣍ͷঢ়ଶΛද͢Έ࡞Δ RemoteResource<T, E>.apply(Next<T, E>) -> RemoteResource<T, E>
w "DUJPOʹNext<T, E>͚ͩ࣋ͨͤΔ w 3FEVDFS͕apply͢Δ
3FEVY4BHB
3FEVY w 3FEVYঢ়ଶͷཧʹಛԽ͍ͯ͠Δ w ࡞༻ w ݱ࣮ͷΞϓϦέʔγϣϯ෭࡞༻Λ࣋ͭ
3FEVY4BHB w 3FEVYNJEEMFXBSF w ෭࡞༻ඇಉظੑΛղܾ͢Δ w (FOFSBUPSGVODUJPO
࣌ࠁ const updateTime = createAction('UPDATE_TIME', (time: Date) => ({ time:
time })); const timeReducer = handleAction(updateTime, (state, action) => action.payload!.time, new Date() ); function * ticktack() { while (true) { yield put(updateTime(new Date())); yield delay(1000); } } function * rootSaga() { yield all([ fork(ticktack), ]); }
࣌ࠁ const sagaMiddleware = createSagaMiddleware(); const store = createStore( combineReducers({
time: timeReducer, }), applyMiddleware(sagaMiddleware) ); sagaMiddleware.run(rootSaga);
࣌ࠁ import * as React from 'react'; import {connect} from
'react-redux'; interface TimeProps { time: Date, } const Time: React.SFC<TimeProps> = ({time}) => { return <time dateTime={time.toISOString()}>{time.toLocaleString()}</time>; }; export default connect(state => ({ time: state.time }))(Time);
3FEVY4BHB w 8FC"1*ͷΞΫηε w takeF⒎FDUͰGetSomeRequested"DUJPOΛͭ w ϦΫΤετ͢Δ w putF⒎FDUͰSomeRecieved"DUJPOΛ͛Δ
8FCϖʔδͱͯ͠ͷ41"
8FCϖʔδͱͯ͠ͷ41" w 41"8FCϒϥβͰಈ࡞͢Δ w 8FCϒϥβʹ8FCಛ༗ͷࣄ͕͋Δ w 63- w )JTUPSZ
63- w 3FBDU3PVUFSW w શͯͷϖʔδʹ63-ΛׂΓৼΔ w MPDBUJPOͷมԽʹԠͯ͡$PNQPOFOUΛΓସ͑Δ w ։ൃதʹϦϩʔυͰ͖ͯศར w
(PPHMF"OBMZUJDTͳͲͱ૬ੑ͕Α͍
)JTUPSZ w ϒϥβͷʮΔʯલͷॴʹΔ w φϏήʔγϣϯͷʮΔʯϘλϯ w ҙຯ্ͷ্Ґ֊ʹͬͯ΄͍͠ w ͦ͜Ͱ͞ΒʹϒϥβͷʮΔʯΛԡͨ͠Βʁ Δ
)JTUPSZ w ʮΔʯઌ͕લͷϖʔδͳΒ window.history.back() w ʮΔʯઌ͕લͷϖʔδͰͳ͚Ε window.history.replaceState() A1 A2 A3
B1 B2 C1 C2 A1 A2 B2
)JTUPSZ w MPDBUJPOʹIJTUPSZTUBUFؚΊΔ w QVTI4UBUFͰIJTUPSZTUBUFʹલ ͷMPDBUJPOΛอଘ͢Δ w IJTUPSZTUBUFʮΔʯʮਐΉʯ Ͱ෮ݩ͞ΕΔ w
ৗʹલͷϖʔδ͕ಘΒΕΔ export interface Location { pathname: Pathname; search: Search; state: LocationState; hash: Hash; key: LocationKey; } window.history.pushState({ lastLocation: location, }, "A2", "/a/2");
·ͱΊ
w 41"(6*ΞϓϦέʔγϣϯ w ঢ়ଶͷཧ͕ॏཁ w 3FBDU 3FEVYͳͲΛ͏·͘͏ w ߴͳϢʔβʔΠϯλʔϑΣʔεΛ࣮ݱͰ͖Δ