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

Fix #3492: throw warning when use class component and suspense #3515

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

guochengcheng04
Copy link

Fix #3492

  • unit test all passed.
  • performance all passed.

@changeset-bot
Copy link

changeset-bot bot commented Sep 5, 2022

🦋 Changeset detected

Latest commit: af5313d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
mobx-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@guochengcheng04
Copy link
Author

@mweststrate hi bro, do you have any ideas about this PR?

Copy link
Collaborator

@urugator urugator left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the comment: #3492 (comment)

@guochengcheng04 guochengcheng04 force-pushed the handle-suspense branch 2 times, most recently from 1d0f0a4 to 0a8854a Compare September 5, 2022 21:29
@@ -0,0 +1,12 @@
declare class FinalizationRegistryType<T> {
Copy link
Collaborator

@urugator urugator Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to import these utils from mobx-react-lite?

Copy link
Collaborator

@urugator urugator Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, it's a slightly artifical, but you can this[reactionTrackingRefSymbol] = React.createRef()

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, it's a slightly artifical, but you can this[reactionTrackingRefSymbol] = React.createRef()

Yes, but I don't think it's necessary. When a function component uses ref, because it can't get the component instance, the class component can directly cache this to achieve the same effect

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason not to import these utils from mobx-react-lite?

If you think this is more reasonable, I can modify it here. Initially, a separate file was created for decoupling between different packages

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, mobx-react already depends on mobx-react-lite, it more or less only adds class support.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i will do it

@@ -165,6 +191,11 @@ function createReactiveRender(originalRender: any) {
isRenderingPending = false
// Create reaction lazily to support re-mounting #3395
const reaction = (reactiveRender[mobxAdminProperty] ??= createReaction())

if (!this[reactionTrack]) {
addReactionToTrack(this, reaction, {})
Copy link
Collaborator

@urugator urugator Sep 6, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move at the end of createReaction, otherwise you would have to clear this[reactionTrack] whenever reactiveRender[mobxAdminProperty] is cleared.
EDIT: Taking it back as you have to do it anyway, because the existence of this[reactionTrack] is used as a check whether the reaction was disposed.

Component.prototype.forceUpdate.call(this)
this[reactionTrack].changedBeforeMount = false
}
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order for this to happen, you have to unset this[reactionTrack] in componentWillUnmount, like here

reactionTrackingRef.current!.reaction.dispose()
reactionTrackingRef.current = null

And also this[reactionTrack] must be unset when reaction is disposed in tracking utils, is it the case?

@urugator
Copy link
Collaborator

urugator commented Sep 6, 2022

Btw, I didn't want to get into it initially, but for completeness, it can also be done without tracking utils in the following fashion:

// timeout could be used as well
const queueMicrotask = window.queueMicrotask ?? (microtask) => Promise.resolve().then(microtask)

// in render
queueMicrotask(() => { 
  if (!mounted) {
     disposeReaction()
  }
})

// in componentDidMount
mounted = true
if (reactionDisposed) {
  recreateReaction() // can be done lazily in render
  forceUpdate()
} else if (reactionNotified) { // state changed in beetwen
  forceUpdate()
}

This is because componenDidMount is quaranteed to run sychronously (before the microtask).
The same can be done with functional components, but we would have to use useLayoutEffect instead of useEffect - could have negative impact on concurrent features, dunno.

@guochengcheng04
Copy link
Author

@urugator all change have done, check please, thank you

@guochengcheng04
Copy link
Author

@urugator Can you help me approve and publish? If need me to do anything please tell me

@guochengcheng04
Copy link
Author

@urugator Can you help me approve and publish? If need me to do anything please tell me

@mweststrate @kubk hi, can we merge and publish to finish this pr?

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

Successfully merging this pull request may close these issues.

An exception is thrown when using Mobx6 and react18 in development mode
3 participants