-
-
Notifications
You must be signed in to change notification settings - Fork 66
Description
When EventListener mounts, it attaches event listeners to all of the elements returned by getSources, which is either the collection of its children, or document if it has no children. When it unmounts, instead of removing these specific event listeners, it calls getSources again - but the collection of children may have changed in the meantime.
Usually when EventListener unmounts, it takes its children with it. However, in specific circumstances, this can cause the entire dash application to become non-functional.
- If at the time of the initial call to
getSourcesthere were no children, the event listener is attached to thedocument - If children are later added dynamically, then when
EventListenerunmounts it will not remove the event listener fromdocument - Then, when the event fires, the event handler will try to set the props on a nonexistent object
- This corrupts dash's state and results in the incredibly difficult to diagnose error message
An object was provided as `children` instead of a component, string, or number (or list of those). Check the children property that looks something like:
{
"props": {
"n_events": 3
}
}
- I've seen this propagate into something which can make the entire app cease to function, but I can't pin down the exact steps that make that happen. When it does happen, the above error message seems to contain a much larger object.
I ran into this by putting an EventListener around dash_quill which lazy loads the Quill editor with no placeholder in the DOM. Having understood the problem, I was able to workaround the issue by wrapping the quill editor in a div rather than nesting it directly below the EventListener.
Suggestions
- Save the list of elements we add event listeners to and use the same list to remove them at unmount
logging=Truedidn't give that much useful information (except show me that the event listener was still being fired even after I expected it to be unmounted, which eventually got me on the right track). Perhaps we can extend the logging to log the list of elements that we're modifying the event listeners of on mount/unmount?- I found it very unintuitive that the EventListener defaulted to adding one to the document even though I passed in a non-empty list of children in Python. I know that this is documented, but it still seemed unexpected (I've been using plenty of EventListeners around my application, and never came across this functionality). In an ideal world I think defaulting to
documentwould be an opt-in feature, but obviously this breaks backwards compatibility.