Render Hook
Loading "Double Confirmation Feature"
Run locally for transcripts
Here's a quick example:
function MyComponent() {
const dc = useDoubleCheck()
return (
<Form method="POST" action="/feed/lions">
<button
{...dc.getButtonProps({
// put custom props here,
// like an onClick, etc...
})}
>
{dc.doubleCheck ? 'Are you sure?' : 'Feed the lions'}
</button>
</Form>
)
}
The first time it's clicked, it calls
preventDefault
on the event and updates
the doubleClick
value. The second time it's clicked, it submits the form.In both cases, any custom
onClick
handler will be called (which can then check
the event.defaultPrevented
value to see if the event was prevented).I want you to try both
renderHook
and TestComponent
for this exercise.
Sometimes you just have to do it both ways and see which you dislike the least.
๐
Let's start with
renderHook
. Here's a reminder of how to use that API:import { renderHook, act } from '@testing-library/react'
import { expect, test } from 'vitest'
import { useCounter } from './use-counter'
test('increments and decrements', () => {
const { result } = await renderHook(() => useCounter(0))
expect(result.current.count).toBe(0)
act(() => result.current.increment())
expect(result.current.count).toBe(1)
act(() => result.current.decrement())
expect(result.current.count).toBe(0)
})
Remember the warning before:
Be sure to always reference values off of
result.current
. Do not destructure
values off of result.current
and then reference them. This will lead you to
referencing stale values and your tests won't work reliably.vi.fn
๐จโ๐ผ In this exercise, you're going to need to use a mock function to pass as the
custom
onClick
handler to make sure it's called when the button is clicked.Here's how you use
vi.fn
to create a mock function:const myClickHandler = vi.fn()
// ... pass the mock function just like you would a regular function
expect(myClickHandler).not.toHaveBeenCalled()
// or
expect(myClickHandler).toHaveBeenCalledTimes(1)
// or
expect(myClickHandler).toHaveBeenCalledWith('some', 'arguments')
// etc.
MouseEvent
๐จโ๐ผ Another thing you will need in this exercise is an event you can call
onClick
with. Because we're not rendering a component, we can't just click a
button to call the click handler. We need to call it ourselves with our own:const clickEvent = new MouseEvent('click', { bubbles: true, cancelable: true })
Regarding TypeScript, sadly, our hook expects a
React.MouseEvent
which we have
no way of creating ourselves. So you're going to need to cast it like this:const clickEvent = new MouseEvent('click', {
bubbles: true,
cancelable: true,
}) as unknown as React.MouseEvent<HTMLButtonElement>
npx vitest double