Skip to content

Commit

Permalink
good progress
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Apr 1, 2024
1 parent dfe6244 commit 7c0578d
Show file tree
Hide file tree
Showing 228 changed files with 10,555 additions and 182 deletions.
2 changes: 1 addition & 1 deletion exercises/01.exercises/08.solution.hydrate/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const initialContentPromise = RSC.createFromFetch(
{ moduleBaseURL },
)

export function Root() {
function Root() {
return use(initialContentPromise).root
}

Expand Down
2 changes: 1 addition & 1 deletion exercises/01.exercises/09.problem.routing/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const initialContentPromise = RSC.createFromFetch(
{ moduleBaseURL },
)

export function Root() {
function Root() {
return use(initialContentPromise).root
}

Expand Down
4 changes: 2 additions & 2 deletions exercises/01.exercises/09.solution.routing/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ if (!initialContentKey) {
}
contentCache.set(initialContentKey, initialContentPromise)

export function Root() {
function Root() {
const [, forceRender] = useReducer(() => Symbol(), Symbol())
const latestNav = useRef(null)
const [nextLocation, setNextLocation] = useState(getGlobalLocation)
Expand Down Expand Up @@ -92,7 +92,7 @@ export function Root() {
return () => window.removeEventListener('popstate', handlePopState)
}, [])

async function navigate(nextLocation, { replace = false, contentKey } = {}) {
function navigate(nextLocation, { replace = false, contentKey } = {}) {
setNextLocation(nextLocation)
const thisNav = Symbol()
latestNav.current = thisNav
Expand Down
13 changes: 6 additions & 7 deletions exercises/01.exercises/09.solution.routing/src/ship-search.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import { useSpinDelay } from './spin-delay.js'

export function ShipSearch({ search, results, fallback }) {
const { navigate, location, nextLocation } = useRouter()
const previousSearch = parseLocationState(nextLocation).search
const nextSearch = parseLocationState(location).search
const isShipSearchPending = useSpinDelay(previousSearch !== nextSearch, {
delay: 300,
minDuration: 350,
})
const isShipSearchPending = useSpinDelay(
parseLocationState(nextLocation).search !==
parseLocationState(location).search,
{ delay: 300, minDuration: 350 },
)

return h(
Fragment,
Expand Down Expand Up @@ -59,7 +58,7 @@ export function SelectShipLink({ shipId, highlight, children }) {
href: `/${shipId}`,
style: { fontWeight: highlight ? 'bold' : 'normal' },
onClick: event => {
if (event.metaKey || event.ctrlKey) return
if (event.ctrlKey || event.metaKey || event.shiftKey) return
event.preventDefault()
const newLocation = mergeLocationState(location, { shipId })
navigate(newLocation)
Expand Down
4 changes: 2 additions & 2 deletions exercises/01.exercises/10.problem.actions/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ if (!initialContentKey) {
}
contentCache.set(initialContentKey, initialContentPromise)

export function Root() {
function Root() {
const [, forceRender] = useReducer(() => Symbol(), Symbol())
const latestNav = useRef(null)
const [nextLocation, setNextLocation] = useState(getGlobalLocation)
Expand Down Expand Up @@ -92,7 +92,7 @@ export function Root() {
return () => window.removeEventListener('popstate', handlePopState)
}, [])

async function navigate(nextLocation, { replace = false, contentKey } = {}) {
function navigate(nextLocation, { replace = false, contentKey } = {}) {
setNextLocation(nextLocation)
const thisNav = Symbol()
latestNav.current = thisNav
Expand Down
13 changes: 6 additions & 7 deletions exercises/01.exercises/10.problem.actions/src/ship-search.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import { useSpinDelay } from './spin-delay.js'

export function ShipSearch({ search, results, fallback }) {
const { navigate, location, nextLocation } = useRouter()
const previousSearch = parseLocationState(nextLocation).search
const nextSearch = parseLocationState(location).search
const isShipSearchPending = useSpinDelay(previousSearch !== nextSearch, {
delay: 300,
minDuration: 350,
})
const isShipSearchPending = useSpinDelay(
parseLocationState(nextLocation).search !==
parseLocationState(location).search,
{ delay: 300, minDuration: 350 },
)

return h(
Fragment,
Expand Down Expand Up @@ -59,7 +58,7 @@ export function SelectShipLink({ shipId, highlight, children }) {
href: `/${shipId}`,
style: { fontWeight: highlight ? 'bold' : 'normal' },
onClick: event => {
if (event.metaKey || event.ctrlKey) return
if (event.ctrlKey || event.metaKey || event.shiftKey) return
event.preventDefault()
const newLocation = mergeLocationState(location, { shipId })
navigate(newLocation)
Expand Down
4 changes: 2 additions & 2 deletions exercises/01.exercises/10.solution.actions/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ if (!initialContentKey) {
}
contentCache.set(initialContentKey, initialContentPromise)

export function Root() {
function Root() {
const [, forceRender] = useReducer(() => Symbol(), Symbol())
const latestNav = useRef(null)
const [nextLocation, setNextLocation] = useState(getGlobalLocation)
Expand Down Expand Up @@ -113,7 +113,7 @@ export function Root() {
return () => window.removeEventListener('popstate', handlePopState)
}, [])

async function navigate(nextLocation, { replace = false, contentKey } = {}) {
function navigate(nextLocation, { replace = false, contentKey } = {}) {
setNextLocation(nextLocation)
const thisNav = Symbol()
latestNav.current = thisNav
Expand Down
13 changes: 6 additions & 7 deletions exercises/01.exercises/10.solution.actions/src/ship-search.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,11 @@ import { useSpinDelay } from './spin-delay.js'

export function ShipSearch({ search, results, fallback }) {
const { navigate, location, nextLocation } = useRouter()
const previousSearch = parseLocationState(nextLocation).search
const nextSearch = parseLocationState(location).search
const isShipSearchPending = useSpinDelay(previousSearch !== nextSearch, {
delay: 300,
minDuration: 350,
})
const isShipSearchPending = useSpinDelay(
parseLocationState(nextLocation).search !==
parseLocationState(location).search,
{ delay: 300, minDuration: 350 },
)

return h(
Fragment,
Expand Down Expand Up @@ -59,7 +58,7 @@ export function SelectShipLink({ shipId, highlight, children }) {
href: `/${shipId}`,
style: { fontWeight: highlight ? 'bold' : 'normal' },
onClick: event => {
if (event.metaKey || event.ctrlKey) return
if (event.ctrlKey || event.metaKey || event.shiftKey) return
event.preventDefault()
const newLocation = mergeLocationState(location, { shipId })
navigate(newLocation)
Expand Down
3 changes: 2 additions & 1 deletion exercises/02.no-ssr/05.solution.client/src/error-boundary.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// https://github.com/bvaughn/react-error-boundary/issues/182
'use client'

export * from 'react-error-boundary'
export { ErrorBoundary } from 'react-error-boundary'
3 changes: 1 addition & 2 deletions exercises/02.no-ssr/05.solution.client/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ const getGlobalLocation = () =>
window.location.pathname + window.location.search

const initialLocation = getGlobalLocation()
const initialContentFetchPromise = fetch(`/rsc${initialLocation}`)
const initialContentPromise = createFromFetch(initialContentFetchPromise, {
const initialContentPromise = createFromFetch(fetch(`/rsc${initialLocation}`), {
moduleBaseURL,
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,3 @@ export function SearchResultsFallback() {
),
)
}

export function ShipResultsErrorFallback() {
return h(
'div',
{ style: { padding: 6, color: '#CD0DD5' } },
'There was an error retrieving results',
)
}
1 change: 1 addition & 0 deletions exercises/02.no-ssr/06.problem.router/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
3 changes: 3 additions & 0 deletions exercises/02.no-ssr/06.problem.router/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
package-lock.json
built_node_modules
35 changes: 35 additions & 0 deletions exercises/02.no-ssr/06.problem.router/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"arrowParens": "avoid",
"bracketSameLine": false,
"bracketSpacing": true,
"embeddedLanguageFormatting": "auto",
"endOfLine": "lf",
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"jsxSingleQuote": false,
"printWidth": 80,
"proseWrap": "always",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": false,
"singleAttributePerLine": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": true,
"overrides": [
{
"files": ["**/*.json"],
"options": {
"useTabs": false
}
},
{
"files": ["**/*.mdx"],
"options": {
"proseWrap": "preserve",
"htmlWhitespaceSensitivity": "ignore"
}
}
]
}
1 change: 1 addition & 0 deletions exercises/02.no-ssr/06.problem.router/README.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Client Router
59 changes: 59 additions & 0 deletions exercises/02.no-ssr/06.problem.router/db/ship-api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import fs from 'node:fs/promises'

const shipData = JSON.parse(
String(await fs.readFile(new URL('./ships.json', import.meta.url))),
)

const MIN_DELAY = 200
const MAX_DELAY = 500

export async function searchShips({
search,
delay = Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY,
}) {
const endTime = Date.now() + delay
const ships = shipData
.filter(ship => ship.name.toLowerCase().includes(search.toLowerCase()))
.slice(0, 13)
await new Promise(resolve => setTimeout(resolve, endTime - Date.now()))
return {
ships: ships.map(ship => ({ name: ship.name, id: ship.id })),
}
}

export async function getShip({
shipId,
delay = Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY,
}) {
const endTime = Date.now() + delay
if (!shipId) {
throw new Error('No shipId provided')
}
const ship = shipData.find(ship => ship.id === shipId)
await new Promise(resolve => setTimeout(resolve, endTime - Date.now()))
if (!ship) {
throw new Error(`No ship with the id "${shipId}"`)
}
return ship
}

export async function updateShipName({
shipId,
shipName,
delay = Math.random() * (MAX_DELAY - MIN_DELAY) + MIN_DELAY,
}) {
const endTime = Date.now() + delay
const ship = shipData.find(ship => ship.id === shipId)
await new Promise(resolve => setTimeout(resolve, endTime - Date.now()))
if (!ship) {
throw new Error(`No ship with the id "${shipId}"`)
}
if (shipName.toLowerCase().includes('error')) {
throw new Error('Error updating ship name')
}
if (shipName === ship.name) {
throw new Error('New name is the same as the old name')
}
ship.name = shipName
return ship
}
Loading

0 comments on commit 7c0578d

Please sign in to comment.