-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(v2): use on events fixes #6711
Conversation
|
} else if (isPromise(jsx)) { | ||
return maybeThen<JSXOutput, JSXNode<string> | null>(jsx, (jsx) => findFirstStringJSX(jsx)); | ||
} else if (isSignal(jsx)) { | ||
return findFirstStringJSX(untrack(() => jsx.value as JSXOutput)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the important change. We could get the jsx from a promise or a signal value, so we need to check if the returned value is a JSXNode.
} else if (isDev) { | ||
logWarn( | ||
'You are trying to add an event using `useOn` hook, ' + | ||
'but a node to which you can add an event is not found. ' + | ||
'Please make sure that the component has a valid element node. ' | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have added a warning message for dev mode if someone is trying to use useOn
hook on the invisible component. We can't handle that, because we don't have any element node to add an event to.
/** | ||
* This hook is like the `useSequentialScope` but it is specifically for `useOn`. This is needed | ||
* because we want to execute the `useOn` hooks only once and store the event listeners on the host | ||
* element. From Qwik V2 the component is rerunning when the promise is thrown, so we need to make | ||
* sure that the event listeners are not added multiple times. | ||
* | ||
* - The event listeners are stored in the `USE_ON_LOCAL` property. | ||
* - The `USE_ON_LOCAL_SEQ_IDX` is used to keep track of the index of the hook that calls this. | ||
* - The `USE_ON_LOCAL_FLAGS` is used to keep track of whether the event listener has been added or | ||
* not. | ||
*/ | ||
const useOnEventsSequentialScope = () => { | ||
const iCtx = useInvokeContext(); | ||
const hostElement = iCtx.$hostElement$; | ||
const host: HostElement = hostElement as any; | ||
let onMap = iCtx.$container2$.getHostProp<UseOnMap>(host, USE_ON_LOCAL); | ||
if (onMap === null) { | ||
onMap = {}; | ||
iCtx.$container2$.setHostProp(host, USE_ON_LOCAL, onMap); | ||
} | ||
let seqIdx = iCtx.$container2$.getHostProp<number>(host, USE_ON_LOCAL_SEQ_IDX); | ||
if (seqIdx === null) { | ||
seqIdx = 0; | ||
} | ||
iCtx.$container2$.setHostProp(host, USE_ON_LOCAL_SEQ_IDX, seqIdx + 1); | ||
let addedFlags = iCtx.$container2$.getHostProp<boolean[]>(host, USE_ON_LOCAL_FLAGS); | ||
if (addedFlags === null) { | ||
addedFlags = []; | ||
iCtx.$container2$.setHostProp(host, USE_ON_LOCAL_FLAGS, addedFlags); | ||
} | ||
while (addedFlags.length <= seqIdx) { | ||
addedFlags.push(false); | ||
} | ||
const addEvent = (eventName: string, eventQrl: EventQRL<KnownEventNames>) => { | ||
addedFlags[seqIdx] = true; | ||
let events = onMap![eventName]; | ||
if (!events) { | ||
onMap![eventName] = events = []; | ||
} | ||
events.push(eventQrl); | ||
}; | ||
|
||
return { | ||
isAdded: addedFlags[seqIdx], | ||
addEvent, | ||
}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does anyone has any better idea?
This PR fixes few edge cases for the
useOn
hook