GithubHelp home page GithubHelp logo

Off topic about jsx-dom HOT 6 CLOSED

alex-kinokon avatar alex-kinokon commented on August 20, 2024
Off topic

from jsx-dom.

Comments (6)

fregante avatar fregante commented on August 20, 2024

Interestingly, another React package from GitHub (https://github.com/primer/components) doesn't work at all

import React from 'jsx-dom';
import {SelectMenu} from '@primer/components';

document.body.append(<SelectMenu/>)

By default:

error TS2786: 'SelectMenu' cannot be used as a JSX component.
  Its return type 'ReactElement<any, any> | null' is not a valid JSX element.

72  document.body.append(<SelectMenu/>)
                          ~~~~~~~~~~

With that FC type:

error TS2786: 'SelectMenu' cannot be used as a JSX component.
  Its return type 'ReactElement<any, any> | null' is not a valid JSX element.
    Type 'ReactElement<any, any>' is not assignable to type 'ReactElement | null'.
      Type 'ReactElement<any, any>' is missing the following properties from type 'SVGElement': className, ownerSVGElement, viewportElement, addEventListener, and 217 more.

72  document.body.append(<SelectMenu/>)
                          ~~~~~~~~~~

from jsx-dom.

Kir-Antipov avatar Kir-Antipov commented on August 20, 2024

Really good question. Should this be supported? As for me, I don't think so. If we provide our react-module polyfill, we kind of say that jsx-dom fully supports all its functionality, so any project that uses React can use jsx-dom as well. But it's not true


For example, you provided a link to the @primer/components library. And it simply cannot be paired with jsx-dom since it's hugely dependent on React!

Some details of source code of the SelectMenu component:

import React, {useCallback, useEffect, useRef, useState} from 'react'

// ...

const SelectMenu = React.forwardRef<HTMLElement, SelectMenuInternalProps>(
  // ...
  return (
    <MenuContext.Provider value={menuProviderValues}>
      <StyledSelectMenu ref={ref} {...rest} open={open} onToggle={toggle}>
        {children}
      </StyledSelectMenu>
    </MenuContext.Provider>
  )
);

And its transpiled version:

var _react = _interopRequireWildcard(require("react"));

// ...

const SelectMenu = _react.default.forwardRef(({
  // ...
  return /*#__PURE__*/_react.default.createElement(_SelectMenuContext.MenuContext.Provider, {
    value: menuProviderValues
  }, /*#__PURE__*/_react.default.createElement(StyledSelectMenu, _extends({
    ref: ref
  }, rest, {
    open: open,
    onToggle: toggle
  }), children));
);

Does jsx-dom have forwardRef, useCallback, useEffect? Nope =>
We can't just go and create an alias like react <-> jsx-dom in this case =>
_react.default.createElement won't create HTMLElement =>
TypeScript doesn't lie to you and its output really cannot be used as jsx-dom's JSX.Element


Considering all of the above, I'm confident that jsx-dom should not include a react module definition, giving its users the false assurance that it can completely replace React. If you want to pair some React library with jsx-dom, it's your responsibility to make sure everything is compatible and everything works just fine, not jsx-dom's

from jsx-dom.

fregante avatar fregante commented on August 20, 2024

Gotcha, but this is just a JSX type issue. Actual compatibility with the module is secondary and is discovered at runtime.

from jsx-dom.

fregante avatar fregante commented on August 20, 2024

Also, the package implements noop React methods specifically to attempt React compatibility. I think it’s totally reasonable to also expect that some basic code (the octicon returns plain SVG JSX) would also be accepted by the types.

If it runs but the types don’t work, then the types are incomplete.

If, like on the second case, it doesn’t run at all, the type problem is secondary, but I hadn’t gotten to actually running the code yet.

from jsx-dom.

Kir-Antipov avatar Kir-Antipov commented on August 20, 2024

If it runs but the types don’t work, then the types are incomplete.

Disagree, you didn't get my point :)

Well,

  1. We have package A1 that has similar to A0 functionality. A1 is not replacement for A0, it's just similar
  2. We have package B that depends on A0

Is B compatible with A1? In general, the answer is: "No"
But there're some cases when we can swap A0 with A1 and B won't notice the difference. Is this good practice? No. Replacing one library with another is a really hacky way to do things, especially if the replacement functionality doesn't fully match the original one. It may work today, but it also may break tomorrow, who knows?


And now let's look at @primer/octicons-react, a specific case that compatible with jsx-dom. How did you know, that it's compatible? (Well, ok, I bet you've tried it already, but let's imagine this is a "fresh start")

  1. Compiler complains about @primer/octicons-react, since jsx-dom honestly says that in general it's incompatible with React libraries

  2. But you have a hope that these libraries can still be combined, so you inspect @primer/octicons-react and make sure that it really doesn't use any functionality that is not available in jsx-dom. This is important 'cause you can fully verify it, but the compiler cannot

  3. And now that you are sure that the two libraries are compatible with each other, you take this responsibility upon yourself and reassure the compiler that everything's fine. And now the responsibility for the fact that the library is compatible and will be compatible with jsx-dom lies solely with you. And that's wright way to do such things, 'cause even hacky solutions, no, especially hacky solutions should be verified and compile-/transpile-time. So this statement:

Actual compatibility with the module is secondary and is discovered at runtime

is kinda wrong. Why do you use TypeScript if you check your code's vitality at runtime? Maybe you should switch to plain JavaScript?


specifically to attempt React compatibility

Well, I used the word "compatibility" before, but now I think that the right one would be "similarity", yeah


And I also want to cite scientific knowledge (aka "how did others do the same thing") as an argument: lets take a look at Preact which is "React but better" by design. Just like jsx-dom it's similar to React, and a lot of simple packages like @primer/octicons-react won't notice any difference. But in general it's incompatible with React, so there's no module "react" definition, and, as a result, no false assurance for users that everything "just works".

Preact's target is similarity with React, not compatibility. Just like jsx-dom's, I believe. If we want compatibility, it's possible (I think) make another library like jsx-dom-compat (similar to Preact's approach), but it's another long story :)


I also can't help but notice how quickly people are changing. You moved from:

— Why in the world do we need props?

to

— I want to take this library, combine it with another library, that targets React, and make everything work

really quickly :D

from jsx-dom.

fregante avatar fregante commented on August 20, 2024

Wow I don’t even know what you’re doing in this repo. This whole ordeal is hacky and TypeScript isn’t really set up in a way that knows anything other than React for JSX. You know that. The readme knows that. Don’t come telling me “why are you even using TypeScript.”

You just went from not knowing how JSX works to writing tomes about a library you discovered the next week. The PR you sent was wrong many times and that’s why I had to reject it and fix it and prove to you m that your assumptions were incorrect. As far as I know I’m done discussing this with you.

from jsx-dom.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.