イベントを起動する際にパラメータを渡したいときはdetail
の中に値を入れて渡す。
const obj :MyObject = { id: id + 1 }
document.dispatchEvent(new CustomEvent('custom-event', { detail: obj }))
イベントリスナーのイベントハンドラには、as EventListenerOrEventListenerObject
もしくはas EventListener
のように型アサーションを書く。
const handleEvent = ((event: CustomEvent<MyObject>) => {
setId(event.detail.id)
}) as EventListenerOrEventListenerObject
document.addEventListener('custom-event', handleEvent)
サンプル
import React, { useEffect, useState } from 'react'
import './App.css'
interface MyObject {
id: number
}
function App () {
const [id, setId] = useState(0)
useEffect(() => {
const handleEvent = ((event: CustomEvent<MyObject>) => {
setId(event.detail.id)
}) as EventListenerOrEventListenerObject
document.addEventListener('custom-event', handleEvent)
return () => {
document.removeEventListener('custom-event', handleEvent)
}
})
const onClick = () => {
console.log('onClick')
const obj :MyObject = { id: id + 1 }
document.dispatchEvent(new CustomEvent('custom-event', { detail: obj }))
}
return (
<div className="App">
<p>{id}</p>
<button onClick={onClick}>Event Dispatch</button>
</div>
)
}
export default App
ユニットテスト
useCustomEvent.ts
import { useEffect, useState } from 'react'
export interface MyObject {
id: number
}
export const useCustomEvent = () => {
const [id, setId] = useState(0)
useEffect(() => {
const handleEvent = ((event: CustomEvent<MyObject>) => {
setId(event.detail.id)
}) as EventListenerOrEventListenerObject
document.addEventListener('custom-event', handleEvent)
return () => {
document.removeEventListener('custom-event', handleEvent)
}
})
return { id }
}
useCustomEvent.test.ts
import { renderHook } from '@testing-library/react-hooks'
import { useCustomEvent } from './useCustomEvent'
import { act } from '@testing-library/react'
describe('custom-event', () => {
test('event listener', () => {
const { result } = renderHook(() => useCustomEvent())
act(() => {
document.dispatchEvent(new CustomEvent('custom-event', { detail: { id: 1 } }))
})
expect(result.current.id).toBe(1)
})
})
参考