Search code examples
reactjsscalajs-react

ReactComponent vs ReactComponentElement in scalajs-react


I am trying to write some extra scalajs-react documentation but I am confused.

It says here :

A ReactElement is a ReactDOMElement or a React component.

But it says here:

type ReactElement = ReactComponentElement | ReactDOMElement;

Which one is true ?

How can one explain this contradiction ?

How can ReactComponent and ReactComponentElement be the same ?

I am confused. Can someone please unconfuse me ?


Solution

  • Perhaps I'm over simplifying, but the source code indicates that a ReactElement is a javascript object with the properties of a ReactNode and key and ref properties. I wouldn't put as much stock in the vDom / scaladoc comments. They exist to provide a hint to the user, not the compiler. It's trying to say "ReactElement is the common base trait to ReactComponentElement and ReactDomElement", which you can see is indeed true.

       /** ReactElement = ReactComponentElement | ReactDOMElement  */
    @js.native
    trait ReactElement extends Object with ReactNode {
      def key: UndefOr[String] = js.native
      def ref: UndefOr[String] = js.native
    }
    
    /** A React virtual DOM element, such as 'div', 'table', etc. */
    @js.native
    trait ReactDOMElement extends ReactElement {
      def `type`: String = js.native
      def props : Object = js.native
    }
    
    /** An instance of a React component. Prefer using the subtype ReactComponentU instead. */
    @js.native
    trait ReactComponentElement[Props]
      extends ReactElement
         with HasProps[Props]
    

    The key thing here is that React is a a fairly dynamic javascript framework, so in order to add type safety around it scala.js there end up being a number of "similar but not identical" subtypes create to handle the various underlying states. For instance, ReactComponentU and friends and ReactComponent/ReactComponentElement.

    I think in order to document it (more?) successfully than it already has been, you probably will have to document React itself, and then paper over it with the type system -- trying to explain things strictly in terms of the scala.js interface is likely to be quite confusing.