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

Nested media queries cause state update on unmounted component #100

Closed
gersomvg opened this issue Sep 18, 2018 · 11 comments
Closed

Nested media queries cause state update on unmounted component #100

gersomvg opened this issue Sep 18, 2018 · 11 comments
Labels

Comments

@gersomvg
Copy link

The error can be reproduced when scaling down this codepen from above 720px to below 720px:

https://codepen.io/gersomvg/pen/yxQgBB

@edorivai
Copy link
Collaborator

I'm sorry, can you elaborate. What is happening for you, what do you expect to happen?

@gersomvg
Copy link
Author

Just check the error in the console, when scaling down the window ;) Visually everything works as expected, but behind the screens React warns for changing state on an unmounted components.

The child component tries to update when the media query becomes falsey, but it is already being unmounted by the parent components that implements the same media query. Normally this should be prevented by a proper componentWillUnmount logic, but I think there is some race condition.

@edorivai
Copy link
Collaborator

peek 2018-09-19 12-45

I'm probably missing something, but I'm not getting any warnings.

@gersomvg
Copy link
Author

gersomvg commented Sep 19, 2018

We're getting somewhere. It looks like it's Safari specific. Maybe browsers have different timing, when it comes to firing events.

@edorivai
Copy link
Collaborator

Ah I see. Yeah so we're already removing the event listener for media query changes in componentWillUnmount. And since the only place that we setState is located within that event handler, I guess we can conclude that in Safari, the media query handler is called before componentWillUnmount, but after the component is actually unmounted 🤔.

This doesn't really make sense. I'm running Linux myself, so it's kinda hard for me to reproduce this. I would really appreciate if you could get some more info on what happens in which exact order.

@gersomvg
Copy link
Author

Yeah, that's super weird. That would mean that for the child component it fires one cycle later than for the parent component.

I'll see what I can do here, debugging-wise...

@yiochen
Copy link
Contributor

yiochen commented Sep 21, 2018

The parent and the child have the same media query. When the media query gets triggered, the engine pushes two events to the event queue to be executed. The first event calls parent's setState, which will unmount the child, the second event calls child's setState. Looks like Safari doesn't do a good job of clearing out events already in the queue, even if the event listener is removed. I wrote a simple test in jsbin:

var mediaQuery = '(min-width: 500px)';
var media = window.matchMedia(mediaQuery);
function listener1() {
  console.log('listener1');
  media.removeListener(listener2);
}
function listener2() {
  console.log('listener2');
}
media.addListener(listener1);
media.addListener(listener2);

When we increase the width to more then 500px, we should only see listener1 (verified with Chrome). But on Safari, I was able to see both listener1 and listener2.

http://jsbin.com/labaciqigu/edit?js,console,output

@edorivai
Copy link
Collaborator

@yiochen thanks for the write up, that makes a lot of sense.

Soooo I guess this is a Safari bug?

@gersomvg
Copy link
Author

@yiochen Thanks indeed. I guess we can solve this easily, by making a thin wrapper around the addListener and removeListener that prevents this bug from happening. I'm happy to write a PR for this, if desired.

@edorivai
Copy link
Collaborator

PR's welcome :)

@JerryMissTom
Copy link

@edorivai @Gersom-NL I come across this bug in my computer. The same code in https://codepen.io/gersomvg/pen/yxQgBB , I resize the Chrome several times, then it will show error info in Console. The screenshot is below
屏幕快照 2019-09-24 下午2 01 49

My computer is Mac Pro, OS version is 10.14.6 (18G95), and Chrome version is 76.0.3809.87 (64 bit)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

4 participants