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

Added host to hooks for instanceof check #100

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

nerocui
Copy link

@nerocui nerocui commented Dec 16, 2022

Hi @ZeeCoder , thanks for creating this library. We are using this package, and we'd like to help make it better. Our use case includes passing in child window's window object. instanceof checks the prototype, and that's unique on each window. So to make sure instanceof works reliably, we need to pass in the host object and compare to the correct Element. Default case is the global window object.

Hope you could give this PR a look when you are free. Thank you!

@ZeeCoder
Copy link
Owner

Hi @nerocui 👋

First of all: thank you, I really appreciate the effort here!

Can you provide a reproduction of your issue in codesandbox, so that I better understand your use-case please? 🙏

@nerocui
Copy link
Author

nerocui commented Jan 3, 2023

@ZeeCoder Happy new year. Hope you had a good holiday break.
I was not able to get it to work with codesandbox, but I uploaded a minimal repro to here https://github.com/nerocui/host-repro
It's just a express app that host two static html pages. Essentially it's just showing that instanceof returns false if an element is created from a different window. So in order to get instanceof to work reliably, it needs to be called with the type from the host window.

Please let me know if this helps.

@ZeeCoder
Copy link
Owner

Sorry I didn't come back to you yet, I'm extremely busy with personal stuff right now but I just wanted you to know I appreciate the time you've invested here.
Seems like the issue stems from useResolvedElement's use of instanceof here:

// Ugly ternary. But smaller than an if-else block.
const element: T | null = cbElement
? cbElement
: refOrElement
? refOrElement instanceof Element
? refOrElement
: refOrElement.current
: null;

I think one solution would be to change this:

    const element: T | null = cbElement
      ? cbElement
      : refOrElement
      ? refOrElement instanceof Element
        ? refOrElement
        : refOrElement.current
      : null;

To this:

    const element: T | null = cbElement
      ? cbElement
      : refOrElement
      ? "current" in refOrElement
        ? refOrElement.current
        : refOrElement
      : null;

☝️ Basically by not using instanceof at all, we circumvent the issue altogether.

Could be a minor release. 🤔

@ZeeCoder ZeeCoder added the enhancement New feature or request label Feb 18, 2023
@ZeeCoder
Copy link
Owner

Would need an additional test case ofc to ensure there'd be no regressions.
Which is where most of the work lies tbh.

@nerocui
Copy link
Author

nerocui commented Feb 18, 2023

@ZeeCoder Thank you so much for looking into it! Yes getting rid of interaction with global objects would solve this issue.

@nerocui
Copy link
Author

nerocui commented Feb 18, 2023

I'll update the PR with the recommendation and test cases.

@bpinto
Copy link

bpinto commented Feb 22, 2023

Alternatively, using hasOwnProperty:

    const element =
      cbElement ||
      (refOrElement
        ? Object.prototype.hasOwnProperty.call(refOrElement, 'current')
          ? refOrElement.current
          : refOrElement
        : null)

@ZeeCoder
Copy link
Owner

@bpinto looks about right, it's a shame that TS doesn't handle it properly though:
image
I mean there must be a reason why this isn't working. 🤔

@bpinto
Copy link

bpinto commented Feb 26, 2023

Sorry @ZeeCoder, I have 0 experience with TS but a google search showed me the following solution:

Type assertion since we know it's a ref and not an element/state:

const element =
  cbElement ||
  (refOrElement
    ? Object.prototype.hasOwnProperty.call(refOrElement, 'current')
      ? (refOrElement as RefObject<T>).current
      : refOrElement as T
    : null)

I tested it here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants