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

node.contains is not a function in Portal click #3786

Closed
xumix opened this issue Sep 16, 2019 · 17 comments
Closed

node.contains is not a function in Portal click #3786

xumix opened this issue Sep 16, 2019 · 17 comments
Labels

Comments

@xumix
Copy link

xumix commented Sep 16, 2019

Bug Report

Can't actually create a valid bug report, looks like passed node is not a real DOM node.
The issue appeared after this PR I suppose: #2384
Here is a similar issue in react dropzone react-dropzone/react-dropzone#763
and here https://stackoverflow.com/questions/50133673/this-node-contains-does-not-work-if-this-node-is-a-ref-to-react-component

Expected Result

Clicks work as intended

Actual Result

No click events are fired

Node here is:

node: {…}
​_reactInternalFiber: {…}
​_reactInternalInstance: {…}
​computeElementType:Button/<()
​computeTabIndex:Button/<()
​context: {}
​focus:Button/<()
​handleClick:Button/<()
​hasIconClass:Button/<()
​props: {…}
​ref: {…}
​refs: {}
​state: null
​updater: {…}
​<prototype>: {…}
TypeError: node.contains is not a functiondoesNodeContainClick.js:25
    doesNodeContainClick doesNodeContainClick.js:25
    Portal Portal.js:59
    dispatchEvent event-stack.development.js:162
    dispatchEvent event-stack.development.js:284
    EventTarget event-stack.development.js:340
    forEach self-hosted:3739
    EventTarget event-stack.development.js:339

Version

0.88.1

@layershifter
Copy link
Member

Please provide a repro case.

@xumix
Copy link
Author

xumix commented Sep 17, 2019

@layershifter any chance for investigation w/o repro?
I've tried to isolate it, but have too many deps in this modal :(

@layershifter
Copy link
Member

How? 🤔

As I see it because wrong ref to trigger/content. I also can be that SUIR Button is used and a ref to it should be captured.

There is only one obvious case than can be an issue:

const CustomButton = React.forwardRef((props, ref) => {
  return <Button {...props} ref={ref} />
})

Try to simplify your Modal by maximum and provide a clean repro. Then I can provide a solution/fix.

@xumix
Copy link
Author

xumix commented Sep 17, 2019

Yup. looks like it's StyledComponent button as trigger that is the cause

import { Button } from "semantic-ui-react";
import styled from "styled-components/macro";

import semanticStyles from "../../../semantic/exports.module.less";

export const LinkButton = styled(Button).attrs({
  //className: "tertiary"
})`
  color: ${semanticStyles.blue} !important;
  font-weight: normal !important;
  padding: 0 !important;
  background-color: transparent !important;
`;
<React.Fragment>
        <Modal
          centered={false}
          trigger={<LinkButton onClick={this.handleOpen}>{this.props.elementText}</LinkButton>}
          dimmer={"inverted"}
          open={this.state.modalOpen}
          onClose={this.handleClose}
          size={"large"}>
          <Modal.Header>{r.offerName}</Modal.Header>
          <Modal.Content scrolling>
            <OfferSkuMatchComponent
              isAdmin={isAdmin}
            />
          </Modal.Content>
          <Modal.Actions>
            <Button primary onClick={this.handleClose}>
              Закрыть
            </Button>
          </Modal.Actions>
        </Modal>
      </React.Fragment>

@xumix
Copy link
Author

xumix commented Sep 17, 2019

Now, looks like it's Styled design decision, I just don't get how do I forward ref to styled button
https://www.styled-components.com/docs/advanced#refs
They pass ref to component instance instead of DOM node, so here is the problem I suppose

@layershifter
Copy link
Member

Let me create a repro and ensure 👍

@layershifter
Copy link
Member

layershifter commented Sep 17, 2019

Here is a workaround for you. Can you please check?

const ButtonWithRef = React.forwardRef((props, ref) => (
  <Ref innerRef={ref}>
    <Button {...props} />
  </Ref>
));

export const WorkingButton = styled(ButtonWithRef)`
  color: green !important;
`;

https://codesandbox.io/s/semantic-ui-example-oxqmt

@xumix
Copy link
Author

xumix commented Sep 17, 2019

@layershifter Thank you for your efforts! It worked!

@xumix
Copy link
Author

xumix commented Sep 17, 2019

Does this mean that now I must use this workaround every time I use StyledComponents and Modals?

@layershifter
Copy link
Member

Yep and Popups, too. As in your case ref will be forwarded to the class component. I know about this issue, but I don't how it can be improved right now.

@xumix
Copy link
Author

xumix commented Sep 17, 2019

Well, this is really unfortunate :(
Also now I'm getting this in console:

Warning: Failed prop type: The prop `innerRef` is marked as required in `Ref`, but its value is `null`.
    in Ref (at LinkButtonStyles.tsx:8)
    in ForwardRef (created by Context.Consumer)
    in StyledComponent (created by LinkButtonStyles__LinkButton)

when I use the button without trigger and modal

@layershifter
Copy link
Member

Can you please edit CodeSandbox to show your issue?

@xumix
Copy link
Author

xumix commented Sep 18, 2019

@layershifter I've managed to make it work like this:

const ButtonWithRef = (React.forwardRef((props, ref) =>
  ref ? (
    <Ref innerRef={ref}>
      <Button {...props} />
    </Ref>
  ) : (
    <Button {...props} />
  )
) as any) as typeof Button;

@layershifter
Copy link
Member

Good to know, closing for now.

@bionicvapourboy
Copy link

bionicvapourboy commented Nov 22, 2019

In my case (Styled Component issue) this simple trick has done the job:

const RefButton = props => <StyledButton {...props} />;

@zgrybus
Copy link

zgrybus commented Feb 15, 2021

Any updates? Would be nice, if you could fix this issue.

@loucadufault
Copy link

TypeScript:

import React from 'react'
import { Button, Ref } from 'semantic-ui-react'

const ButtonWithRef = React.forwardRef<HTMLElement>((props, ref) => (
  <Ref innerRef={ref}>
    <Button {...props} />
  </Ref>
)) as any as typeof Button

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

No branches or pull requests

5 participants