#Component created using Dynamic doesn't have reactive props

24 messages · Page 1 of 1 (latest)

rain thorn
#

To simplify things, I have this helper function:

const mkComp = (tag: string) =>
  (props: Record<string, any>) =>
    Dynamic.bind(null, { component: tag, ...props })

and I have a component created using it that looks like this:

const ButtonAlt = mkComp('button')

However, the ButtonAlt component ends up with non reactive props, meaning that when it's props changes it doesn't re-render, I tried testing this same code by making it's children change from "loading" to "test" through user interaction and it doesn't work, any clues?

arctic prism
#

Hm, there's no JSX there - so I don't think that Solid's compiler can kick in here.

#

Would
createComponent(Dynamic, props)
work?

rain thorn
#

Since the the tag is a variable I don't know I could do that using JSX, basically what I want is an equivalent to React's createElement

arctic prism
rain thorn
#

I see, I will test that, I just didn't find that function listed in the API documentation

arctic prism
#

Maybe not documented.

rain thorn
#

One thing tho, it does work if I wrap the Dynamic call inside createMemo, but I think that recreates the component entirelly whenever props change

arctic prism
#

Hm, doesn't feel right. Try createComponent

#

As I said, not using JSX is probably preventing the compiler to kick in. This should work, in theory.\

rain thorn
#

Like so?

const mkEl = (tag: string) => (props: Record<string, any>) => {
  return createComponent(Dynamic({ component: tag  }), props)
}
#

I was trying to find where the function was declared and exported in the code base but I got lost, seems to be in the solid-js/web package I think

#

Didn't seem to work that way

#

nor this way

const mkEl = (tag: string) => (props: Record<string, any>) => {
  return createComponent(
    Dynamic.bind(null, { component: tag  }),
    props)
}
arctic prism
#

Like

import { createComponent,  mergeProps } from "solid-js";
import { Dynamic } from "solid-js/web";

const mkEl = (tag: string) => (props: Record<string, unknown>) => {
 const props_ = mergeProps(props, { component: el });
 return createComponent(Dynamic, props_);
}
rain thorn
#

That works perfectly, thanks a lot! pepehyper

arctic prism
#
<Dynamic component={state.component} someProp={state.something} />
#

I might be missing something, but seems to me that by using this, merging props, you could easily
write JSX and let the compiler kick in.

rain thorn
#

It happens that I'm basically trying to port a React lib to Solid.js, and honestly I'm mostly trying to translate the way they did it with React to Solid, and they don't use JSX in the function in question. The lib that I'm trying to port is a css-in-js lib called Stitches:
https://github.com/stitchesjs/stitches

GitHub

CSS-in-JS with near-zero runtime, SSR, multi-variant support, and a best-in-class developer experience. - GitHub - stitchesjs/stitches: CSS-in-JS with near-zero runtime, SSR, multi-variant support,...

#

And this is the piece of code in question

export const createStyledFunction = ({ config, sheet }) =>
    createCssFunctionMap(config, () => {
        const cssFunction = createCssFunction(config, sheet)

        const _styled = (
            args,
            css = cssFunction,
            { displayName, shouldForwardStitchesProp } = {}
        ) => {

            const cssComponent = css(...args)
            const DefaultType = cssComponent[internal].type
            const shouldForwardAs = shouldForwardStitchesProp?.('as')

            const styledComponent = (props) => {
                const tag = props?.as && !shouldForwardAs
                    ? props?.as : DefaultType

                const {
                    props: forwardProps,
                    deferredInjector
                } = cssComponent(props)

                console.log({ props, deferredInjector })

                const component = createComponent(Dynamic, mergeProps(
                    forwardProps,
                    { component: tag }))

                if (!shouldForwardAs) delete forwardProps.as

                if (deferredInjector) return createComponent(Fragment, {
                    children: [
                        component,
                        createComponent(Dynamic, { component: deferredInjector })
                    ]
                })

                return component
            }

            const toString = () => cssComponent.selector

            styledComponent.className = cssComponent.className
            styledComponent.selector = cssComponent.selector
            styledComponent.toString = toString
            styledComponent[internal] = cssComponent[internal]
            styledComponent.displayName = displayName ||
                `Styled.${DefaultType.displayName
                    || DefaultType.name
                    || DefaultType}`

            return styledComponent
        }

        const styled = (...args) => _styled(args)

        styled.withConfig = (componentConfig) => (...args) => {
            const cssWithConfig = cssFunction
                .withConfig(componentConfig)

            return _styled(args, cssWithConfig, componentConfig)
        }

        return styled
    })
#

(hardly legible through Discord markdown, I'm sorry)

#

I think I actually tried using JSX to test as well and the result was the same =/