Skip to content

Unable to find node on an unmounted component  #3562

Closed
@punmechanic

Description

@punmechanic

Bug Report

This report demonstrates an issue in which a component which uses <RefFindNode> will cause a React tree crash because findDOMNode(this) is called after a component has been unmounted.

Steps

Here is a Code Sandbox which demonstrates the issue. You should open this in Firefox as Chrome will not display the precise error due to the error being cross-origin.

https://codesandbox.io/s/v8m974m98l

My understanding of the problem is that if a user unmounts a Semantic component that utilises <RefFindNode /> after its initial mount, Semantic may attempt to access the DOM Node of that element after it is unmounted, causing a full app tree crash. A great way to demonstrate this is by using React.useEffect() and throwing a Promise after initial render.

In the sandbox above, you can see this by throwing a Promise to simulate React Suspense from within a Semantic <Modal />, for which the button is a trigger. The Promise is thrown after the first render due to the usage of useEffect() and useState().

This can be taped over reinforced by enclosing the component which throws (FetchyChildren) in React.Suspense which prevents the thrown Promise from propagating up the chain, such that the thrown Promise does not result in the Button being unmounted.

  const modal = (
    <EditModal>
      <React.Suspense>
        <FetchyChildren />
      </React.Suspense>
    </EditModal>
  );

This does appear to be specific to Promises: Throwing a generic error allows the error to propagate normally through to the usual lifecycles. It's only when throwing a Promise that I've seen so far that causes an app tree crash.

Expected Result

There should be no runtime error related to findDOMNode() or full app tree crash.

Full expected behaviour is unclear, since in this case the <Modal /> is the owner of its open/closed state and will get unmounted. I'd need someone more knowledgeable on the ins and outs of how Suspense works with its app tree to know the intended behaviour, but I'm pretty sure a full app tree crash is not it :)

Actual Result

React App tree goes boom

Version

Semantic UI React 0.68.0
React 16.8.6
React DOM 16.8.6

Testcase

Apologies, I don't have time to fork your codesandbox right now because I have to go to a meeting, but I prepared a sandbox while trying to repro the bug from my own code and am happy to port it over though it should be reasonably understandable. Run the tests in Firefox because Chrome will not display the test error.

Unfortunately, it's not possible to use an assertion like expect(() => act(() => button.click())).toThrow() because there will be a weird error to do with code sandbox thrown.

https://codesandbox.io/s/v8m974m98l

This is related to #3255, which states that wrapping your button with forwardRef will solve the issue - Unfortunately, the problem is within Semantic components and not userland ones. One way I have managed to patch over this is to indeed create a custom button component with forwardRef, but Semantic's Button is still broken.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions