File tree Expand file tree Collapse file tree 9 files changed +153
-23
lines changed Expand file tree Collapse file tree 9 files changed +153
-23
lines changed Original file line number Diff line number Diff line change 1- import React , { Component } from 'react' ;
1+ import React , { useContext , useState , Suspense } from 'react' ;
22
33import Chrome from './Chrome' ;
44import Page from './Page' ;
5+ import Page2 from './Page2' ;
6+ import Theme from './Theme' ;
57
6- export default class App extends Component {
7- render ( ) {
8- return (
9- < Chrome title = "Hello World" assets = { this . props . assets } >
10- < div >
11- < h1 > Hello World</ h1 >
12- < Page />
13- </ div >
14- </ Chrome >
15- ) ;
16- }
8+ function LoadingIndicator ( ) {
9+ let theme = useContext ( Theme ) ;
10+ return < div className = { theme + '-loading' } > Loading...</ div > ;
11+ }
12+
13+ export default function App ( { assets} ) {
14+ let [ CurrentPage , switchPage ] = useState ( ( ) => Page ) ;
15+ return (
16+ < Chrome title = "Hello World" assets = { assets } >
17+ < div >
18+ < h1 > Hello World</ h1 >
19+ < a className = "link" onClick = { ( ) => switchPage ( ( ) => Page ) } >
20+ Page 1
21+ </ a >
22+ { ' | ' }
23+ < a className = "link" onClick = { ( ) => switchPage ( ( ) => Page2 ) } >
24+ Page 2
25+ </ a >
26+ < Suspense fallback = { < LoadingIndicator /> } >
27+ < CurrentPage />
28+ </ Suspense >
29+ </ div >
30+ </ Chrome >
31+ ) ;
1732}
Original file line number Diff line number Diff line change 33 padding : 0 ;
44 font-family : sans-serif;
55}
6+
7+ body .light {
8+ background-color : # FFFFFF ;
9+ color : # 333333 ;
10+ }
11+
12+ body .dark {
13+ background-color : # 000000 ;
14+ color : # CCCCCC ;
15+ }
16+
17+ .light-loading {
18+ margin : 10px 0 ;
19+ padding : 10px ;
20+ background-color : # CCCCCC ;
21+ color : # 666666 ;
22+ }
23+
24+ .dark-loading {
25+ margin : 10px 0 ;
26+ padding : 10px ;
27+ background-color : # 333333 ;
28+ color : # 999999 ;
29+ }
Original file line number Diff line number Diff line change 11import React , { Component } from 'react' ;
22
3+ import Theme , { ThemeToggleButton } from './Theme' ;
4+
35import './Chrome.css' ;
46
57export default class Chrome extends Component {
8+ state = { theme : 'light' } ;
69 render ( ) {
710 const assets = this . props . assets ;
811 return (
@@ -14,13 +17,18 @@ export default class Chrome extends Component {
1417 < link rel = "stylesheet" href = { assets [ 'main.css' ] } />
1518 < title > { this . props . title } </ title >
1619 </ head >
17- < body >
20+ < body className = { this . state . theme } >
1821 < noscript
1922 dangerouslySetInnerHTML = { {
2023 __html : `<b>Enable JavaScript to run this app.</b>` ,
2124 } }
2225 />
23- { this . props . children }
26+ < Theme . Provider value = { this . state . theme } >
27+ { this . props . children }
28+ < div >
29+ < ThemeToggleButton onChange = { theme => this . setState ( { theme} ) } />
30+ </ div >
31+ </ Theme . Provider >
2432 < script
2533 dangerouslySetInnerHTML = { {
2634 __html : `assetManifest = ${ JSON . stringify ( assets ) } ;` ,
Original file line number Diff line number Diff line change 1- .bold {
1+ .link {
22 font-weight : bold;
3+ cursor : pointer;
4+ }
5+ .light-box {
6+ margin : 10px 0 ;
7+ padding : 10px ;
8+ background-color : # CCCCCC ;
9+ color : # 333333 ;
10+ }
11+ .dark-box {
12+ margin : 10px 0 ;
13+ padding : 10px ;
14+ background-color : # 333333 ;
15+ color : # CCCCCC ;
316}
Original file line number Diff line number Diff line change 11import React , { Component } from 'react' ;
22
3+ import Theme from './Theme' ;
4+ import Suspend from './Suspend' ;
5+
36import './Page.css' ;
47
58const autofocusedInputs = [
@@ -14,17 +17,22 @@ export default class Page extends Component {
1417 } ;
1518 render ( ) {
1619 const link = (
17- < a className = "bold " onClick = { this . handleClick } >
20+ < a className = "link " onClick = { this . handleClick } >
1821 Click Here
1922 </ a >
2023 ) ;
2124 return (
22- < div >
23- < p suppressHydrationWarning = { true } > A random number: { Math . random ( ) } </ p >
24- < p > Autofocus on page load: { autofocusedInputs } </ p >
25- < p > { ! this . state . active ? link : 'Thanks!' } </ p >
26- { this . state . active && < p > Autofocus on update: { autofocusedInputs } </ p > }
25+ < div className = { this . context + '-box' } >
26+ < Suspend >
27+ < p suppressHydrationWarning = { true } >
28+ A random number: { Math . random ( ) }
29+ </ p >
30+ < p > Autofocus on page load: { autofocusedInputs } </ p >
31+ < p > { ! this . state . active ? link : 'Thanks!' } </ p >
32+ { this . state . active && < p > Autofocus on update: { autofocusedInputs } </ p > }
33+ </ Suspend >
2734 </ div >
2835 ) ;
2936 }
3037}
38+ Page . contextType = Theme ;
Original file line number Diff line number Diff line change 1+ import React , { useContext } from 'react' ;
2+
3+ import Theme from './Theme' ;
4+ import Suspend from './Suspend' ;
5+
6+ import './Page.css' ;
7+
8+ export default function Page2 ( ) {
9+ let theme = useContext ( Theme ) ;
10+ return (
11+ < div className = { theme + '-box' } >
12+ < Suspend > Content of a different page</ Suspend >
13+ </ div >
14+ ) ;
15+ }
Original file line number Diff line number Diff line change 1+ let promise = null ;
2+ let isResolved = false ;
3+
4+ export default function Suspend ( { children} ) {
5+ // This will suspend the content from rendering but only on the client.
6+ // This is used to demo a slow loading app.
7+ if ( typeof window === 'object' ) {
8+ if ( ! isResolved ) {
9+ if ( promise === null ) {
10+ promise = new Promise ( resolve => {
11+ setTimeout ( ( ) => {
12+ isResolved = true ;
13+ resolve ( ) ;
14+ } , 6000 ) ;
15+ } ) ;
16+ }
17+ throw promise ;
18+ }
19+ }
20+ return children ;
21+ }
Original file line number Diff line number Diff line change 1+ import React , { createContext , useContext , useState } from 'react' ;
2+
3+ const Theme = createContext ( 'light' ) ;
4+
5+ export default Theme ;
6+
7+ export function ThemeToggleButton ( { onChange} ) {
8+ let theme = useContext ( Theme ) ;
9+ let [ targetTheme , setTargetTheme ] = useState ( theme ) ;
10+ function toggleTheme ( ) {
11+ let newTheme = theme === 'light' ? 'dark' : 'light' ;
12+ // High pri, responsive update.
13+ setTargetTheme ( newTheme ) ;
14+ // Perform the actual theme change in a separate update.
15+ setTimeout ( ( ) => onChange ( newTheme ) , 0 ) ;
16+ }
17+ if ( targetTheme !== theme ) {
18+ return 'Switching to ' + targetTheme + '...' ;
19+ }
20+ return (
21+ < a className = "link" onClick = { toggleTheme } >
22+ Switch to { theme === 'light' ? 'Dark' : 'Light' } theme
23+ </ a >
24+ ) ;
25+ }
Original file line number Diff line number Diff line change 11import React from 'react' ;
2- import { hydrate } from 'react-dom' ;
2+ import { unstable_createRoot } from 'react-dom' ;
33
44import App from './components/App' ;
55
6- hydrate ( < App assets = { window . assetManifest } /> , document ) ;
6+ let root = unstable_createRoot ( document , { hydrate : true } ) ;
7+ root . render ( < App assets = { window . assetManifest } /> ) ;
You can’t perform that action at this time.
0 commit comments