Skip to content

Commit

Permalink
finish improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed May 9, 2024
1 parent b13dc2d commit ed1fbc0
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 14 deletions.
2 changes: 1 addition & 1 deletion exercises/06.layout-computation/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ It literally has the same API as `useEffect`, but it runs synchronously after
the DOM has been updated. You may recall from the `useEffect` exercise, the
[React flow diagram](https://github.com/donavon/hook-flow):

![React Flow diagram showing mount, update, unmount](https://github-production-user-asset-6210df.s3.amazonaws.com/1500684/295689283-b9ecdd1d-ce28-446b-84ad-6b264d4be8e4.png)
![React Flow diagram showing mount, update, unmount](/hook-flow.png)

The `useLayoutEffect` hook runs after the DOM has been updated but before the
browser has had a chance to paint the screen. This means you can make your
Expand Down
2 changes: 1 addition & 1 deletion exercises/09.sync-external/01.problem.sub/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as ReactDOM from 'react-dom/client'
// 🐨 make a subscribe function here which takes a callback function
// 🐨 create a matchQueryList variable here with the mediaQuery from above (📜 https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList)
// 🐨 add a change listener to the mediaQueryList which calls the callback
// 🐨 return a cleanup function whihc removes the change event listener for the callback
// 🐨 return a cleanup function which removes the change event listener for the callback

function NarrowScreenNotifier() {
// 🐨 assign this to useSyncExternalStore with the subscribe and getSnapshot functions above
Expand Down
15 changes: 15 additions & 0 deletions exercises/09.sync-external/02.problem.util/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,18 @@
query. So please stick most of our logic in a `makeMediaQueryStore` function
and have that return a custom hook people can use to keep track of the current
media query's matching state.

It'll be something like this:

```tsx
export function makeMediaQueryStore(mediaQuery: string) {
// ...
}

const useNarrowMediaQuery = makeMediaQueryStore('(max-width: 600px)')

function App() {
const isNarrow = useNarrowMediaQuery()
// ...
}
```
28 changes: 25 additions & 3 deletions exercises/09.sync-external/03.problem.ssr/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,26 @@ adding some code to the bottom of our file. First, we render the `<App />` to a
string, then we set that to the `innerHTML` of our `rootEl`. Then we call
`hydrateRoot` to rehydrate our application.

```tsx
const rootEl = document.createElement('div')
document.body.append(rootEl)
// simulate server rendering
rootEl.innerHTML = (await import('react-dom/server')).renderToString(<App />)

// simulate taking a while for the JS to load...
await new Promise(resolve => setTimeout(resolve, 1000))

ReactDOM.hydrateRoot(rootEl, <App />)
```

👨‍💼 This is a bit of a hack, but it's a good way to simulate server rendering
and ensure that our application works in a server rendering situation.

Because the server won't know whether a media query matches, we can't use the
`getServerSnapshot()` argument of `useSyncExternalStore`. Instead, we'll leave
that argument off, and wrap our `<NarrowScreenNotifier />` in a `<Suspense />`
component with a fallback of `""` (we won't show anything until the client
hydrates).
that argument off, and wrap our `<NarrowScreenNotifier />` in a
[`<Suspense />`](https://react.dev/reference/react/Suspense) component with a
fallback of `""` (we won't show anything until the client hydrates).

With this, you'll notice there's an error in the console. Nothing's technically
wrong, but React logs this in this situation (I honestly personally disagree
Expand All @@ -25,3 +37,13 @@ includes the string `'Missing getServerSnapshot'` then you can return,
otherwise, log the error.

Good luck!

```tsx
import { hydrateRoot } from 'react-dom/client'

const root = hydrateRoot(document.getElementById('root'), <App />, {
onRecoverableError: (error, errorInfo) => {
console.error('Caught error', error, error.cause, errorInfo.componentStack)
},
})
```
3 changes: 2 additions & 1 deletion exercises/09.sync-external/03.problem.ssr/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ function App() {
return (
<div>
<div>This is your narrow screen state:</div>
{/* 🐨 add a Suspense component around this with a fallback prop */}
{/* 🐨 wrap this in a Suspense component around this with a fallback prop of "" */}
{/* 📜 https://react.dev/reference/react/Suspense */}
<NarrowScreenNotifier />
</div>
)
Expand Down
8 changes: 0 additions & 8 deletions exercises/09.sync-external/README.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,6 @@ function MyLocation() {
</div>
)
}

function App() {
return (
<Suspense fallback="loading location...">
<MyLocation />
</Suspense>
)
}
```

Here's the basic API:
Expand Down
Binary file added public/hook-flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit ed1fbc0

Please sign in to comment.