Skip to content

Commit

Permalink
feat: add useEvent API
Browse files Browse the repository at this point in the history
  • Loading branch information
ambar committed Sep 16, 2021
1 parent aac7c3e commit fa4b671
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 28 deletions.
35 changes: 11 additions & 24 deletions example/src/MP4Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,19 @@ const useQuery = () => {
return query
}

/** 常规通讯方式,建议直接使用 `onEvent` 替代 */
const LogoListener: React.FC<{shouldShowLogo: boolean}> = ({
shouldShowLogo,
}) => {
const [isLogoVisible, setIsLogoVisible] = useState(false)
const {subscribeEvent} = useContext(MessageContext)
useLayoutEffect(() => {
return subscribeEvent(EVENTS.PLAY_COUNT, () => {
setIsLogoVisible(true)
}).unsubscribe
}, [subscribeEvent])
return shouldShowLogo && isLogoVisible ? <Logo /> : null
}

const App = () => {
const messageContextRef = useMessageContextRef()
const query = useQuery()
const loop = 'loop' in query
const messageContextRef = useMessageContextRef()
const [isLogoVisible, setIsLogoVisible] = useState(false)

useEffect(() => {
return messageContextRef.subscribeEvent(EVENTS.ENDED, () => {
if (loop) {
messageContextRef.dispatchAction(ACTIONS.PLAY)
}
}).unsubscribe
}, [messageContextRef, loop])
messageContextRef.useEvent(EVENTS.PLAY_COUNT, () => {
setIsLogoVisible(true)
})
messageContextRef.useEvent(EVENTS.ENDED, () => {
if ('loop' in query) {
messageContextRef.dispatchAction(ACTIONS.PLAY)
}
})

return (
<>
Expand All @@ -101,7 +88,7 @@ const App = () => {
messageContextRef={messageContextRef}
onEvent={logEvent}
>
<LogoListener shouldShowLogo={'logo' in query} />
{'logo' in query && isLogoVisible && <Logo />}
</Player>
<button
onClick={() => {
Expand Down
34 changes: 30 additions & 4 deletions packages/griffith/src/contexts/MessageContext.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, {useEffect, useRef} from 'react'
import React, {useEffect, useLayoutEffect, useRef} from 'react'
import EventEmitter from 'eventemitter3'
import {
ACTIONS,
Expand Down Expand Up @@ -67,13 +67,22 @@ type MessageProviderProps = {

type MessageHelper = ReturnType<typeof createMessageHelper>

const useHandler = <T extends (...args: any[]) => any>(handler: T) => {
const handlerRef = useRef<T>(handler)
handlerRef.current = handler
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return useRef(((...args: any[]) => handlerRef.current(...args)) as T).current
}

/**
*
* Retrieve `MessageContext` from outside of Player
*
* ```js
* const messageContextRef = useMessageContextRef()
*
* messageContextRef.useEvent(EVENTS.PLAY, () => {})
*
* render(
* <>
* <Player messageContextRef={messageContextRef} />
Expand All @@ -83,16 +92,33 @@ type MessageHelper = ReturnType<typeof createMessageHelper>
* ```
*/
export const useMessageContextRef = () => {
const ref = useRef({}).current as MessageContextRef
useEffect(() => {
const extra = {
useEvent<T extends keyof EventParamsMap>(
name: T,
listener: EventParamsMap[T]
) {
const handler = useHandler(listener)
useLayoutEffect(
() => ref.subscribeEvent(name, handler).unsubscribe,
[name, handler]
)
},
}
const ref = useRef(extra).current as MessageContextRef &
MessageContextValue &
typeof extra

// Player mount 中触发了事件,确保在它之前开始监听
useLayoutEffect(() => {
if (!ref.current) {
throw new Error(
'Missing ref value, please pass it to Player, eg. `<Player messageContextRef={messageContextRef} />`'
)
}
Object.assign(ref, ref.current)
}, [ref])
return ref as MessageContextRef & MessageContextValue

return ref
}

export class MessageProvider extends React.PureComponent<MessageProviderProps> {
Expand Down

0 comments on commit fa4b671

Please sign in to comment.