#jsx vs jsxs

1 messages · Page 1 of 1 (latest)

jolly crater
#

When using jsx with the config

"jsx": "react-jsx",
"jsxImportSource": "jsx",

then

const asdf = (
    <div id="parent">
        <div id="child1"></div>
        <div id="child2"></div>
    </div>
);

becomes

import { jsx as _jsx, jsxs as _jsxs } from "jsx/jsx-runtime";
const asdf = _jsxs("div", {
    id: "parent",
    children: [
        _jsx("div", { id: "child1" }),
        _jsx("div", { id: "child2" })
    ] });

what is the difference between jsx() and jsxs()?
i wanna use jsx in a few places but dont want an entire framework.

wanton cove
weak hedgeBOT
#
export { jsx, jsx as jsxs, jsxFragment as Fragment, render, Component }
jolly crater
#

that is good to know but i assume there is a pattern/rule to how tsc chooses what one to use

#

i googled for hours and found no documentation. all i could find containing "jsxs" was that is got imported in examples but never mentioned in the actual text around it

wanton cove
#

Why do you need to know what specific imports it's using when it generates the code?

#

You won't be writing the generated code yourself

jolly crater
#

no, but i was going to write my own tiny runtime just to learn the details of its inner workings. but documentation on jsx transpilation is sparse

wanton cove
#

Ah I see

jolly crater
#

if jsx and jsxs have the same signature then i could use the same factory but there is obviously some intended difference

wanton cove
#

I assume jsxs is made to handle an array of fragments as the children of the node and jsx is for just a single child, and in jsx-runtime they just have an Array.isArray call inside their jsx function instead so it can handle both cases

weak hedgeBOT
#
if (Array.isArray(node.props.children)) {
woeful dagger
#

using jsxs would result in a single 1 child

wanton cove
#

I mean you can use the same function so long as you conditionally return the right children type depending on whether the children is an array, which is what jsx-runtime does

#

Might be cleaner to split it up depending on your implementation though

jolly crater
#

seems jsxs is used when there are multiple children passed in an array

const asdf = (
    <div id="parent">
        <div id="child1">
            <div id="child5"></div>
        </div>
        <div id="child2">
            <div id="child3"></div>
            <div id="child4"></div>
        </div>
    </div>
);

became

import { jsx as _jsx, jsxs as _jsxs } from "jsx/jsx-runtime";
const asdf = _jsxs("div", {
    id: "parent",
    children: [
        _jsx("div", { id: "child1", children: _jsx("div", { id: "child5" }) }),
        _jsxs("div", { id: "child2", children: [_jsx("div", { id: "child3" }), _jsx("div", { id: "child4" })] })
    ]
});
#

thanks to the knowledge you shared i managed to isolate a notable difference

const asdf2 = <p>{[[1],[2]]}</p>;
const asdf3 = <p>{[1]}{[2]}</p>;
const asdf2 = _jsx("p", { children: [[1], [2]] });
const asdf3 = _jsxs("p", { children: [[1], [2]] });
#

this still begs the question. what does it mean to put an array as a child? would casting to a string make sense or is there something more useful?

#

i suppose this is resolved now but i dont know how to mark it

wanton cove
#

!resolved

charred quarryBOT
#

@jolly crater
Because your issue seemed to be resolved, this post was marked as resolved by @wanton cove.
If your issue is not resolved, you can reopen this post by running !reopen.
If you have a different question, make a new post in #1057653400046674112.

jolly crater
#

i see, old style command. kinda expected a dev oriented server to have that updated long ago.

wanton cove
#

Yeah lol

woeful dagger
scenic warren
#
import type { AnyComponentType } from './AnyComponentType.js'
import type { SxyComponentGenericProps } from './SxyComponents.jsx'
import { SxyFrameworkError } from './SxyFrameworkError.js'

export const Fragment = 0xeacb as const // code taken from react for fragments
export const fragmentSymbol = Symbol('fragment')
export type FragmentSymbol = typeof fragmentSymbol

export type JsxNodeType = string | AnyComponentType | typeof Fragment

//// TODO use this symbol for type
export const TypeSymbol = Symbol('type')

// this doesn't seem to handle string/number/undefined correctly

// jsx func to turn a jsx element into a tree node
export function jsx(type: JsxNodeType | string | number | boolean | null | undefined, props: SxyComponentGenericProps) {
    //const { children, ...filteredProps } = props
    if (type === Fragment) {
        const { children } = props
        return children
    }
    if (typeof type === 'function') {
        return {
            type,
            props
        }
    }
    if (typeof type === 'string') {
        return {
            type,
            props
        }
    }
    if (typeof type === undefined || type === null) {
        return type
    }
    if (typeof type === 'number') {
        return String(type)
    }
    throw new SxyFrameworkError(`SXY JSX Runtime error: did not recognize element, expected a string, function, class (type function), or fragment. Received type ${typeof type}: ${type}`)
}

// jsx func for static elements
// not sure exactly what this is, just use the same func for now
export const jsxs = jsx

Here is my JSX runtime, in case it helps

#

Frankly you could compile JSX straight down to the objects returned by jsx() calls, they aren't really needed.

#

At least in my case they are not required

#

It's very straight forward