Skip to content
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

Performance of unmounting a context provider #4347

Open
1 task done
ikolobar opened this issue Apr 24, 2024 · 0 comments
Open
1 task done

Performance of unmounting a context provider #4347

ikolobar opened this issue Apr 24, 2024 · 0 comments

Comments

@ikolobar
Copy link

ikolobar commented Apr 24, 2024

  • Check if updating to the latest Preact version resolves the issue - No

Describe the bug
Unmounting a context provider is slow if there are many components subscribed to its context.

To Reproduce

Steps to reproduce the behavior:

  1. Go to the stackblitz repro
  2. Click "Toggle mounted"
  3. Notice that unmounting takes a while.
  4. Comment out useContext(MyContext) in Component and repeat. It will be much faster.

Expected behavior
It should be faster.

Root cause
Subscribing to a context provider overrides componentWillUnmount:

	        this.sub = function (c) {
	          subs.push(c);
	          var old = c.componentWillUnmount;

	          c.componentWillUnmount = function () {
	            subs.splice(subs.indexOf(c), 1);
	            if (old) { old.call(c); }
	          };
	        };

When unmounting the entire tree, repeatedly splicing the subs array is slow because it shifts the array. If the provider itself is unmounting, it could instead immediately remove all its subs. Alternatively if changing the render order of subscribed components isn't a breaking change, it could avoid the splice cost like this:

            this.sub = function (c) {
              subs.push(c);
              var old = c.componentWillUnmount;

              c.componentWillUnmount = function () {
                var index = subs.indexOf(c);
                var last = subs.pop();
                if (last !== c){
                    subs[index] = last;
                }
                if (old) { old.call(c); }
              };
            };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant