Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Ready for Async Rendering
Search
koba04
April 19, 2018
Programming
6
1.6k
Ready for Async Rendering
Scramble! #1 Frontend
https://folio.connpass.com/event/82816/
koba04
April 19, 2018
Tweet
Share
More Decks by koba04
See All by koba04
フロントエンドの現在地とこれから
koba04
10
5.3k
Standing on the shoulders of giants
koba04
0
3k
React/Next によるアプリケーション開発のこれから
koba04
61
18k
フロントエンド刷新をプロジェクトとして進める際に気をつけていること
koba04
3
1.9k
How useEvent would change our applications
koba04
1
3.1k
kintoneフロントエンド刷新によるモノリスからの脱却とその先に目指す未来
koba04
3
16k
Make it Declarative with React
koba04
0
1.8k
Ready for React in 2019
koba04
2
1.7k
Algorithms in React
koba04
14
17k
Other Decks in Programming
See All in Programming
Reactive Thinking with Signals and the new Resource API
manfredsteyer
PRO
0
130
OSS開発者の憂鬱
yusukebe
14
12k
AIエージェントでのJava開発がはかどるMCPをAIを使って開発してみた / java mcp for jjug
kishida
4
830
高単価案件で働くための心構え
nullnull
0
170
レイトレZ世代に捧ぐ、今からレイトレを始めるための小径
ichi_raven
0
480
Stay Hacker 〜九州で生まれ、Perlに出会い、コミュニティで育つ〜
pyama86
2
2.9k
大体よく分かるscala.collection.immutable.HashMap ~ Compressed Hash-Array Mapped Prefix-tree (CHAMP) ~
matsu_chara
1
180
無秩序からの脱却 / Emergence from chaos
nrslib
1
10k
Module Harmony
petamoriken
2
580
最新のDirectX12で使えるレイトレ周りの機能追加について
projectasura
0
310
Why Kotlin? 電子カルテを Kotlin で開発する理由 / Why Kotlin? at Henry
agatan
1
130
Evolving NEWT’s TypeScript Backend for the AI-Driven Era
xpromx
0
210
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
234
17k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
The Cult of Friendly URLs
andyhume
79
6.7k
Art, The Web, and Tiny UX
lynnandtonic
303
21k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.8k
Leading Effective Engineering Teams in the AI Era
addyosmani
8
1.2k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.6k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Code Reviewing Like a Champion
maltzj
527
40k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Transcript
3FBEZGPS"TZOD3FOEFSJOH 4DSBNCMF !LPCB
None
"HFOEB w 8IBUJT"TZOD3FOEFSJOH w -JGFDZDMF.FUIPET4USJDU.PEF w 5JNF4MJDJOH w 3FBDU4VTQFOTF
w "QQFOEJY v16.3 Changes
8IBUJT"TZOD3FOEFSJOH
w 3FBDU'JCFSJTBOVOJUPGXPSL 㲈3FBDU&MFNFOU w *UJTQPTTJCMFUPTUPQBOESFTVNFVQEBUFT 3FDBQ3FBDU'JCFS FiberA FiberB FiberD
FiberE Commit all SideEffects Idle Time Idle Time Idle Time SideEffect SideEffect Host (DOM) FiberC Render Phase Commit Phase
w 3FOEFS1IBTFʜ"TZOD w $PNNJU1IBTFʜ4ZOD 3FDBQ3FBDU'JCFS FiberA FiberB FiberD FiberE Commit
all SideEffects Idle Time Idle Time Idle Time SideEffect SideEffect Host (DOM) FiberC Async Sync
4VTQFOEBOE3FTVNF FiberA FiberB FiberA FiberC Commit Low Priority Sync Priority
Commit FiberA FiberB FiberC Low Priority Reuse Interrupt Suspend
-JGFDZDMF.FUIPET
$IBOHFTGPSMJGFDZDMFNFUIPET http://blog.koba04.com/post/2018/04/04/react-v163-changes/
w $BMMFEBU3FOEFS1IBTF w 3FUVSOBQBSUJBMTUBUFCBTFEPOOFYU1SPQT w TUBUJDHFU%FSJWFE4UBUF'SPN1SPQT static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.category !== prevState.category) { return { data: null, category: null }; } return null; } componentDidUpdate() { if (this.state.category == null) { fetchData(this.props.category).then((data) => { this.setState({category: this.props.category, data}); }); }
w $BMMFEBU$PNNJU1IBTF w 3FUVSOBTOBQTIPU BOZ CFGPSFVQEBUFUIF)PTU w UIFTOBQTIPUJTQBTTFEUPDPNQPOFOU%JE6QEBUF HFU4OBQTIPU#FGPSF6QEBUF getSnapshotBeforeUpdate()
{ return { scrollHeight: document.body.scrollHeight, scrollTop: document.body.scrollTop, }; } componentDidUpdate(prevProps, prevState, snapshot) { const {body} = document; const {scrollTop, scrollHeight} = snapshot; body.scrollTop = scrollTop + (body.scrollHeight - scrollHeight); }
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#examples
https://github.com/facebook/react/tree/master/packages/create-subscription
4USJDU.PEF
w *EFOUJGZJOHDPNQPOFOUTVOTBGFMJGFDZDMFT w 8BSOJOHBCPVUMFHBDZTUSJOHSFG"1*VTBHF w %FUFDUJOHVOFYQFDUFETJEFF⒎FDUT 4USJDU.PEF const {StrictMode} =
React; const App = () => ( <StrictMode> <Header /> <Main /> <Footer /> </StrictMode> );
/FX$BQBCJMJUJFT
https://reactjs.org/blog/2018/03/01/sneak-peek-beyond-react-16.html
5JNF4MJDJOH
w #MPDLJOH6*UISFBEJTBOBXGVMFYQFSJFODF w 5IFSFBSFNBOZQFPQMFXIPVTFMPXQPXFSEFWJDFT w 8IZOPUEFCPVODFPSUISPUUMF 5IFBOTXFSJTʜ w SFRVFTU*EMF$BMMCBDL 5JNF4MJDJOH
<AsyncMode> <FilterInput onChange={value => { ReactDOM.flushSync(() => this.setState({value})); this.setState({data: this.filterData(value)}); }} /> </AsyncMode>
https://koba04.github.io/react-fiber-resources/examples/ Async Update Sync Update
None
https://zeit.co/blog/domains-search-web
3FBDU4VTQFOTF
https://github.com/facebook/react/pull/12279
w 3FBDU4VTQFOTFJTBGFBUVSFUPIBOEMFBTZODVQEBUFT w )5513FRVFTU w %ZOBNJD-PBEJOH w )BOEMJOHBTZODISPOPVTVQEBUFTBSFTPIBSEʜ w 4UBSU-PBEJOH
"1*4VDDFTT &SSPSʜ w .BOZMPBEJOHTQJOOFST KBOLCZBGBTUSFTQPOTF 3FBDU4VTQFOTF
3FBDU4VTQFOTF "1*XJMMCFDIBOHFE import SimpleCacheProvider from ‘simple-cache-provider’; const cache = SimpleCacheProvider.createCache();
const userFetcher = id => SimpleCacheProvider.createResource(id => fetch(`/api/users/${id}`).then(res => res.json()); )(cache, id); const User = props => { const user = userFetcher.read(props.id); return <div>{user.name}</div>; }; const Fallback = props => ( <React.Timeout ms={props.timeout}> {didExpire => didExpire ? props.placeholder : props.children} </React.Timeout> ); <Fallback placeholder=“Loading…” timeout={200}> <User id={100} /> </Fallback>
3FBDU4VTQFOTF "1*XJMMCFDIBOHFE import SimpleCacheProvider from ‘simple-cache-provider’; const cache = SimpleCacheProvider.createCache();
const routeFetcher = Component => SimpleCacheProvider.createResource(Component => import(Component).then(module => module.default); )(cache, Component); const UserPage = () => { const Component = routeFetcher.read(‘./pages/User’); return <Component />; }; const Fallback = props => ( <React.Timeout ms={props.timeout}> {didExpire => didExpire ? props.placeholder : props.children} </React.Timeout> ); <Fallback placeholder=“Loading…” timeout={1000}> <UserPage /> </Fallback>
Empty Pending Resolved Rejected read or preload throw promise return
value from cache Cache load
w 3FBDU4VTQFOTFJTCBTFEPO&SSPS#PVOEBSJFT UIPVHI XIJDIUISPXT1SPNJTFJOTUFBEPG&SSPS )PXEPFT3FBDU4VTQFOTFXPSL User Fallback Timeout throw Promise!
(suspend) timeout render with fetched Data (resume)
https://github.com/facebook/react/pull/12201
w 5IF"1*JTOPUpOBM"1* NJHIUCFDIBOHFE w *IFBSESFOEFSGVODUJPONVTUOPUIBWFBOZTJEFF⒎FDUT w 3FBDU4VTQFOTFPO443SFOEFSFS w
1SFSFOEFSBOEQSFMPBEJOHXJUIIJEEFOQSPQT w "XFTPNF8IFODBO*VTF3FBDU4VTQFOTF w .BZCFJOʜ 3FBDU4VTQFOTF
"QQFOEJY
/FX$POUFYU"1* const LangContext = React.createContext(‘en’); const ThemeContext = React.createContext(‘dark’); const
App = () => ( <LangContext.Provider value=“en”> <ThemeContext.Provider value=“dark”> <Child> <LangContext.Consumer> {lang => ( <ThemeContext.Consumer> {theme => ( <button className={theme}> {getMessage(‘click’, lang)} </button> )} </ThemeContext.Consumer> )} </LangContext.Consumer> </Child> </ThemeContext.Provider> </LangContext.Provider> );
w )BSEUPUZQFDIFDLJOH w TIPVME$PNQPOFOU6QEBUFNJHIUCSFBLUIFVQEBUF 1SPCMFNTPGMFHBDZ$POUFYU"1* GrandChild Child Parent ThemeContext Brown
-> Orange shouldComponentUpdate return false;
w 0QUJNJ[FUIFVQEBUFTGPS$POUFYUWBMVF w 3FBDUVTFTCJUXJTFPQFSBUPSJUTJOUFSOBMT 0CTFSWFE#JUT VOTUBCMF⚠ const StoreContext = React.createContext(null,
(prev, next) => { let changedBits = 0; if (prev.foo !== next.foo) changedBits |= 0b01; if (prev.bar !== next.bar) changedBits |= 0b10; return changedBits; }); // changedBits & unstable_observedBits !== 0 <StoreContext.Consumer unstable_observedBits={0b01}> {({foo}) => <div>{foo}</div> </StoreContext.Consumer> <StoreContext.Consumer unstable_observedBits={0b10}> {({bar}) => <div>{bar}</div> </StoreContext.Consumer>
https://medium.com/@koba04/a-secret-parts-of-react-new-context-api-e9506a4578aa
w 3FEVYBOE/FX$POUFYUBSFEJ⒎FSFOUMBZFST w SFBDUSFEVYNJHIUCFDIBOHFEXJUI/FX$POUFYU"1* w IUUQTHJUIVCDPNSFBDUKTSFBDUSFEVYQVMM w 8IZBSFZPVVTJOH3FEVY /FX$POUFYUBOE3FEVY
5IBOLT TQFBLFSEFDLDPNLPCB