Skip to content

Commit 7dca270

Browse files
committed
finish exercises and in-code instructions
1 parent ca7c48d commit 7dca270

File tree

15 files changed

+383
-52
lines changed

15 files changed

+383
-52
lines changed

exercises/01.use-state/01.problem.initial-state/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { createRoot } from 'react-dom/client'
22

33
// 🐨 create a `useState` function which accepts the initial state and returns
4-
// an array of the state and a function to update it.
4+
// an array of the state and a no-op function: () => {}
55
// 🦺 note you may need to ignore some typescript errors here. We'll fix them later.
66
// Feel free to make the `useState` a generic though!
77

88
function Counter() {
99
// @ts-expect-error 💣 delete this comment
1010
const [count, setCount] = useState(0)
11+
// 🦺 you'll get an error for this we'll fix that next
1112
const increment = () => setCount(count + 1)
1213
return (
1314
<div className="counter">

exercises/01.use-state/01.solution.initial-state/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { createRoot } from 'react-dom/client'
22

33
function useState<State>(initialState: State) {
4-
let state = initialState
5-
const setState = (newState: State) => (state = newState)
4+
const state = initialState
5+
const setState = () => {}
66
return [state, setState] as const
77
}
88

99
function Counter() {
1010
const [count, setCount] = useState(0)
11+
// @ts-expect-error we'll fix this soon
1112
const increment = () => setCount(count + 1)
1213
return (
1314
<div className="counter">

exercises/01.use-state/02.problem.update-state/index.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { createRoot } from 'react-dom/client'
22

33
function useState<State>(initialState: State) {
4-
let state = initialState
5-
const setState = (newState: State) => (state = newState)
4+
// 🐨 change this to let
5+
const state = initialState
6+
// 🐨 update this to accept newState and assign state to that
7+
const setState = () => {}
68
return [state, setState] as const
79
}
810

911
function Counter() {
1012
const [count, setCount] = useState(0)
13+
// @ts-expect-error 💣 delete this comment
1114
const increment = () => setCount(count + 1)
1215
return (
1316
<div className="counter">

exercises/01.use-state/03.problem.re-render/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createRoot } from 'react-dom/client'
22

33
function useState<State>(initialState: State) {
44
let state = initialState
5+
// 🐨 update this function to call render after setting the state
56
const setState = (newState: State) => (state = newState)
67
return [state, setState] as const
78
}
@@ -19,4 +20,8 @@ function Counter() {
1920
const rootEl = document.createElement('div')
2021
document.body.append(rootEl)
2122
const appRoot = createRoot(rootEl)
23+
24+
// 🐨 place this in a new function called render
2225
appRoot.render(<Counter />)
26+
27+
// 🐨 call render here to kick things off

exercises/01.use-state/03.solution.re-render/index.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ import { createRoot } from 'react-dom/client'
22

33
function useState<State>(initialState: State) {
44
let state = initialState
5-
const setState = (newState: State) => (state = newState)
5+
const setState = (newState: State) => {
6+
state = newState
7+
render()
8+
}
69
return [state, setState] as const
710
}
811

@@ -19,4 +22,9 @@ function Counter() {
1922
const rootEl = document.createElement('div')
2023
document.body.append(rootEl)
2124
const appRoot = createRoot(rootEl)
22-
appRoot.render(<Counter />)
25+
26+
function render() {
27+
appRoot.render(<Counter />)
28+
}
29+
30+
render()

exercises/01.use-state/04.problem.preserve-state/index.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,20 @@
11
import { createRoot } from 'react-dom/client'
22

3+
// 🐨 create state and setState variables here using let
4+
// 🦺 set their type to "any"
5+
36
function useState<State>(initialState: State) {
7+
// 🐨 remove the "let" and "const" here so this function references the
8+
// variables declared above
9+
// 🐨 Next, change this so we only do these assignments if the state is undefined
410
let state = initialState
5-
const setState = (newState: State) => (state = newState)
11+
const setState = (newState: State) => {
12+
state = newState
13+
render()
14+
}
15+
// 🦺 because our state and setState are now typed as any, you may choose to
16+
// update this to as [State, (newState: State) => void] so we can preserve
17+
// the type of state
618
return [state, setState] as const
719
}
820

@@ -19,4 +31,9 @@ function Counter() {
1931
const rootEl = document.createElement('div')
2032
document.body.append(rootEl)
2133
const appRoot = createRoot(rootEl)
22-
appRoot.render(<Counter />)
34+
35+
function render() {
36+
appRoot.render(<Counter />)
37+
}
38+
39+
render()
Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
import { createRoot } from 'react-dom/client'
22

3+
let state: any, setState: any
4+
35
function useState<State>(initialState: State) {
4-
let state = initialState
5-
const setState = (newState: State) => (state = newState)
6-
return [state, setState] as const
6+
if (state === undefined) {
7+
state = initialState
8+
setState = (newState: State) => {
9+
state = newState
10+
render()
11+
}
12+
}
13+
return [state, setState] as [State, (newState: State) => void]
714
}
815

916
function Counter() {
1017
const [count, setCount] = useState(0)
1118
const increment = () => setCount(count + 1)
19+
1220
return (
1321
<div className="counter">
1422
<button onClick={increment}>{count}</button>
@@ -19,4 +27,9 @@ function Counter() {
1927
const rootEl = document.createElement('div')
2028
document.body.append(rootEl)
2129
const appRoot = createRoot(rootEl)
22-
appRoot.render(<Counter />)
30+
31+
function render() {
32+
appRoot.render(<Counter />)
33+
}
34+
35+
render()
Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,53 @@
11
import { createRoot } from 'react-dom/client'
22

3+
// 🐨 create two Symbols for the phase: "INITIALIZATION" and "UPDATE"
4+
// 💯 as extra credit, give them a descriptive name
5+
6+
// 🦺 create a type called Phase which is the typeof INITIALIZATION | typeof UPDATE
7+
8+
// 🐨 create a variable called phase of type Phase and set it to INITIALIZATION
9+
10+
let state: any, setState: any
11+
312
function useState<State>(initialState: State) {
4-
let state = initialState
5-
const setState = (newState: State) => (state = newState)
6-
return [state, setState] as const
13+
// 🐨 change this to check whether the phase is INITIALIZATION
14+
if (state === undefined) {
15+
state = initialState
16+
setState = (newState: State) => {
17+
state = newState
18+
// 🐨 pass the UPDATE phase to render here
19+
render()
20+
}
21+
}
22+
return [state, setState] as [State, (newState: State) => void]
723
}
824

925
function Counter() {
1026
const [count, setCount] = useState(0)
1127
const increment = () => setCount(count + 1)
28+
29+
const [enabled, setEnabled] = useState(true)
30+
const toggle = () => setEnabled(!enabled)
31+
1232
return (
1333
<div className="counter">
14-
<button onClick={increment}>{count}</button>
34+
<button onClick={toggle}>{enabled ? 'Disable' : 'Enable'}</button>
35+
<button disabled={!enabled} onClick={increment}>
36+
{count}
37+
</button>
1538
</div>
1639
)
1740
}
1841

1942
const rootEl = document.createElement('div')
2043
document.body.append(rootEl)
2144
const appRoot = createRoot(rootEl)
22-
appRoot.render(<Counter />)
45+
46+
// 🐨 accept a newPhase argument
47+
function render() {
48+
// 🐨 assign the phase to the newPhase
49+
appRoot.render(<Counter />)
50+
}
51+
52+
// 🐨 call this with the INITIALIZATION phase
53+
render()
Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,47 @@
11
import { createRoot } from 'react-dom/client'
22

3+
const INITIALIZATION = Symbol('phase.initialization')
4+
const UPDATE = Symbol('phase.update')
5+
type Phase = typeof INITIALIZATION | typeof UPDATE
6+
let phase: Phase
7+
8+
let state: any, setState: any
9+
310
function useState<State>(initialState: State) {
4-
let state = initialState
5-
const setState = (newState: State) => (state = newState)
6-
return [state, setState] as const
11+
if (phase === INITIALIZATION) {
12+
state = initialState
13+
setState = (newState: State) => {
14+
state = newState
15+
render(UPDATE)
16+
}
17+
}
18+
return [state, setState] as [State, (newState: State) => void]
719
}
820

921
function Counter() {
1022
const [count, setCount] = useState(0)
1123
const increment = () => setCount(count + 1)
24+
25+
const [enabled, setEnabled] = useState(true)
26+
const toggle = () => setEnabled(!enabled)
27+
1228
return (
1329
<div className="counter">
14-
<button onClick={increment}>{count}</button>
30+
<button onClick={toggle}>{enabled ? 'Disable' : 'Enable'}</button>
31+
<button disabled={!enabled} onClick={increment}>
32+
{count}
33+
</button>
1534
</div>
1635
)
1736
}
1837

1938
const rootEl = document.createElement('div')
2039
document.body.append(rootEl)
2140
const appRoot = createRoot(rootEl)
22-
appRoot.render(<Counter />)
41+
42+
function render(newPhase: Phase) {
43+
phase = newPhase
44+
appRoot.render(<Counter />)
45+
}
46+
47+
render(INITIALIZATION)
Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,57 @@
11
import { createRoot } from 'react-dom/client'
22

3+
const INITIALIZATION = Symbol('phase.initialization')
4+
const UPDATE = Symbol('phase.update')
5+
type Phase = typeof INITIALIZATION | typeof UPDATE
6+
let phase: Phase
7+
// 🐨 make a hookIndex variable here that starts at 0
8+
// 🐨 make a variable called "states" which is an array of arrays (one for each
9+
// return value of a useState call)
10+
11+
// 💣 delete these variable declarations
12+
let state: any, setState: any
13+
314
function useState<State>(initialState: State) {
4-
let state = initialState
5-
const setState = (newState: State) => (state = newState)
6-
return [state, setState] as const
15+
// 🐨 create a variable called "id" and assign it to "hookIndex++"
16+
if (phase === INITIALIZATION) {
17+
// 🐨 assign states[id] to an array with the initialState and the setState function
18+
// rather than assigning the values to the old variables
19+
state = initialState
20+
setState = (newState: State) => {
21+
// 🐨 instead of reassigning the variable state to the newState, update states[id][0] to it.
22+
state = newState
23+
render(UPDATE)
24+
}
25+
}
26+
// 🐨 return the value at states[id] instead of the old variables
27+
return [state, setState] as [State, (newState: State) => void]
728
}
829

930
function Counter() {
1031
const [count, setCount] = useState(0)
1132
const increment = () => setCount(count + 1)
33+
34+
const [enabled, setEnabled] = useState(true)
35+
const toggle = () => setEnabled(!enabled)
36+
1237
return (
1338
<div className="counter">
14-
<button onClick={increment}>{count}</button>
39+
<button onClick={toggle}>{enabled ? 'Disable' : 'Enable'}</button>
40+
<button disabled={!enabled} onClick={increment}>
41+
{count}
42+
</button>
1543
</div>
1644
)
1745
}
1846

1947
const rootEl = document.createElement('div')
2048
document.body.append(rootEl)
2149
const appRoot = createRoot(rootEl)
22-
appRoot.render(<Counter />)
50+
51+
function render(newPhase: Phase) {
52+
// 🐨 set the hookIndex to 0
53+
phase = newPhase
54+
appRoot.render(<Counter />)
55+
}
56+
57+
render(INITIALIZATION)

0 commit comments

Comments
 (0)