Skip to content

Commit

Permalink
06 done
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Mar 8, 2024
1 parent e0e3b5b commit 6df03db
Show file tree
Hide file tree
Showing 22 changed files with 71 additions and 7 deletions.
1 change: 0 additions & 1 deletion exercises/05.portals/01.problem.create/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ export default function Tooltip({
if (!rect) return
const { height } = rect
setTooltipHeight(height)
console.log('Measured tooltip height: ' + height)
}, [])

let tooltipX = 0
Expand Down
1 change: 0 additions & 1 deletion exercises/05.portals/01.solution.create/tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export default function Tooltip({
if (!rect) return
const { height } = rect
setTooltipHeight(height)
console.log('Measured tooltip height: ' + height)
}, [])

let tooltipX = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# useLayoutEffect

👨‍💼 Our tooltip is great, but we do need to make measurements when we display it.
We do this in a `useEffect` hook now with code like this:

```tsx
useEffect(() => {
const rect = ref.current?.getBoundingClientRect()
if (!rect) return
const { height } = rect
setTooltipHeight(height)
}, [])
```

That `height` is used to determine whether the tooltip should appear above or
below the target element (the heart in our case).

Kellie 🧝‍♂️ noticed on low-end devices, they're seeing a little flicker
so <DiffLink app1={-1}>she's added</DiffLink> an arbitrary slowdown to our
component to simulate that problem. To reproduce the problem, simply hover over
a heart and you'll notice it starts at the bottom of the heart and then flickers
to the top (if there's room on the top of the heart).

So your job is simple. Change `useEffect` to `useLayoutEffect` and that should
fix things.

📜 Parts of this exercise was lifted from [the React docs](https://react.dev/reference/react/useLayoutEffect#measuring-layout-before-the-browser-repaints-the-screen)
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export default function Tooltip({
const ref = useRef<HTMLDivElement | null>(null)
const [tooltipHeight, setTooltipHeight] = useState(0)

// 🐨 change this to useLayoutEffect to ensure it runs synchronously after the
// DOM has been updated so the user doesn't see the tooltip jump around.
useEffect(() => {
const rect = ref.current?.getBoundingClientRect()
if (!rect) return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# useLayoutEffect

👨‍💼 Have you ever heard of the mechanic who charged $200 when all he did was
tighten a screw? The customer was outraged and asked for an itemized bill. The
mechanic sent him an invoice that read:

```
Tightening a screw: $1
Knowing which screw to tighten: $199
```

Even though this exercise was really easy, knowing when to use `useLayoutEffect`
is the hard part. It's like knowing which screw to tighten. Good job!
3 changes: 3 additions & 0 deletions exercises/06.layout-computation/FINISHED.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Layout Computation

👨‍💼 Hey... You're awesome. 😎
26 changes: 26 additions & 0 deletions exercises/06.layout-computation/README.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Layout Computation

Sometimes you need to compute the layout of some UI before it is actually
displayed. This is often necessary if the size, position, or location of your UI
depends on the size, position, or location of the other elements on the page or
even itself (like the contents of a tooltip).

The trouble is, sometimes you don't know the size, position, or location of the
other elements on the page until the layout has been computed. So what happens
is you render the UI, then you make your measurements, then you re-render the UI
with the new measurements. This is inefficient and can cause flickering.

To avoid this problem in React, you can use the `useLayoutEffect` hook. This
hook is designed with this specific use case in mind and is not a hook you'll
find yourself needing very often.

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)

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
measurements and then render the UI with the correct measurements before the
user sees anything.
1 change: 0 additions & 1 deletion exercises/06.layout-effect/01.problem/README.mdx

This file was deleted.

1 change: 0 additions & 1 deletion exercises/06.layout-effect/01.solution/README.mdx

This file was deleted.

Empty file.
3 changes: 0 additions & 3 deletions exercises/06.layout-effect/README.mdx

This file was deleted.

0 comments on commit 6df03db

Please sign in to comment.