| name | fix-modus-component-event-issues |
| description | Debug and fix common event handling problems with Modus web components |
Fix Modus Component Event Issues
Debug and fix common event handling problems with Modus web components.
When to Use
Use this skill when:
- Events aren't firing on Modus components
- Components aren't responding to user interactions
- Event handlers aren't being called
- You suspect event listener setup issues
Common Issues and Solutions
Issue 1: Events Not Firing
Symptoms: Click handlers, change handlers, or other events don't fire.
Causes:
- Missing event listener setup
- Wrong event name
- Component ref not set up
- Handler not passed as prop
Solution:
useEffect(() => {
const component = componentRef.current;
if (!component) return;
const handleEvent = (event: Event) => {
onEvent?.(event as CustomEvent<EventDetailType>);
};
if (onEvent) {
component.addEventListener("eventName", handleEvent);
}
return () => {
if (onEvent) {
component.removeEventListener("eventName", handleEvent);
}
};
}, [onEvent]);
Checklist:
Issue 2: Missing Cleanup
Symptoms: Memory leaks, events firing multiple times, component errors after unmount.
Solution:
useEffect(() => {
const component = componentRef.current;
if (!component) return;
const handleEvent = (event: Event) => {
onEvent?.(event as CustomEvent<EventDetailType>);
};
component.addEventListener("eventName", handleEvent);
return () => {
component.removeEventListener("eventName", handleEvent);
};
}, [onEvent]);
Issue 3: Wrong Event Names
Symptoms: Events never fire, wrong event type received.
Common Event Names:
| Component | Event Name | Detail Type |
|---|
| Checkbox | inputChange | InputEvent |
| TextInput | inputChange | InputEvent |
| DropdownMenu | itemSelect | { value: string } |
| DropdownMenu | menuVisibilityChange | { isVisible: boolean } |
| Navbar | searchClick | MouseEvent | KeyboardEvent |
| Accordion | expandedChange | { expanded: boolean; index: number } |
Solution: Check Modus documentation for exact event names. They're case-sensitive.
Issue 4: Missing Ref
Symptoms: Cannot read property 'addEventListener' of null, events don't attach.
Solution:
const componentRef = useRef<HTMLModusWcComponentElement>(null);
useEffect(() => {
const component = componentRef.current;
if (!component) return;
}, []);
return (
<ModusWcComponent ref={componentRef} />
);
Issue 5: Handler Not in Dependencies
Symptoms: Stale closures, handlers use old values.
Solution:
useEffect(() => {
const component = componentRef.current;
if (!component) return;
const handleEvent = (event: Event) => {
onEvent?.(event as CustomEvent<EventDetailType>);
};
if (onEvent) {
component.addEventListener("eventName", handleEvent);
}
return () => {
if (onEvent) {
component.removeEventListener("eventName", handleEvent);
}
};
}, [onEvent]);
Issue 6: Wrong Event Target
Symptoms: Can't access component properties, wrong value extracted.
Solution:
const handleInputChange = (event: Event) => {
const customEvent = event as CustomEvent<InputEvent>;
const value = (customEvent.target as HTMLModusWcTextInputElement).value;
onInputChange?.(value);
};
const handleInputChange = (event: Event) => {
const value = event.detail;
};
Issue 7: Multiple Event Listeners
Symptoms: Events fire multiple times, duplicate handlers.
Solution:
if (onEvent) {
component.addEventListener("eventName", handleEvent);
}
return () => {
if (onEvent) {
component.removeEventListener("eventName", handleEvent);
}
};
Debugging Checklist
When events aren't working, check:
-
Ref Setup
-
Event Listener Setup
-
Cleanup
-
Dependencies
-
Event Handling
Debugging Tools
Console Logging
useEffect(() => {
const component = componentRef.current;
if (!component) {
console.error("Component ref is null");
return;
}
console.log("Setting up event listener for:", component);
const handleEvent = (event: Event) => {
console.log("Event fired:", event);
console.log("Event type:", event.type);
console.log("Event target:", event.target);
onEvent?.(event as CustomEvent<EventDetailType>);
};
component.addEventListener("eventName", handleEvent);
console.log("Event listener attached");
return () => {
console.log("Cleaning up event listener");
component.removeEventListener("eventName", handleEvent);
};
}, [onEvent]);
React DevTools
- Check if component ref is set
- Verify component is mounted
- Check if handlers are defined
Browser DevTools
- Check Event Listeners panel for attached listeners
- Verify event names match
- Check for errors in console
Common Patterns to Verify
Pattern 1: Basic Event Setup
const componentRef = useRef<HTMLModusWcComponentElement>(null);
useEffect(() => {
const component = componentRef.current;
if (!component) return;
const handleEvent = (event: Event) => {
onEvent?.(event as CustomEvent<EventDetailType>);
};
if (onEvent) {
component.addEventListener("eventName", handleEvent);
}
return () => {
if (onEvent) {
component.removeEventListener("eventName", handleEvent);
}
};
}, [onEvent]);
return <ModusWcComponent ref={componentRef} />;
Pattern 2: Multiple Events
useEffect(() => {
const component = componentRef.current;
if (!component) return;
const handleEvent1 = (event: Event) => {
onEvent1?.(event as CustomEvent<Type1>);
};
const handleEvent2 = (event: Event) => {
onEvent2?.(event as CustomEvent<Type2>);
};
if (onEvent1) component.addEventListener("event1", handleEvent1);
if (onEvent2) component.addEventListener("event2", handleEvent2);
return () => {
if (onEvent1) component.removeEventListener("event1", handleEvent1);
if (onEvent2) component.removeEventListener("event2", handleEvent2);
};
}, [onEvent1, onEvent2]);
Quick Fixes
Fix: Events Not Firing
- Check if ref is set:
console.log(componentRef.current)
- Verify event name: Check Modus docs
- Add console.log in handler to verify it's called
- Check if handler prop is passed
Fix: Events Firing Multiple Times
- Check if cleanup is removing listeners
- Verify handler isn't recreated on each render
- Check dependency array includes handler
Fix: Wrong Values
- Verify event type casting
- Check if using
target.value vs detail
- For checkboxes, verify value inversion is handled
Related Files
src/components/ModusCheckbox.tsx - Event handling example
src/components/ModusDropdownMenu.tsx - Multiple events example
src/components/ModusNavbar.tsx - Complex event handling
.cursor/rules/modus-react-integration.mdc - Integration patterns