solidjs / solid-refresh

MIT License
86 stars 18 forks source link

Root component not hot reloaded when using render #64

Open RsMan-Dev opened 7 months ago

RsMan-Dev commented 7 months ago

I have this setup:

globalThis.allComponents = import.meta.glob('/javascripts/components/**/*.{jsx,tsx,js,ts}', {eager: true});

function getComponentByName(name: string) { /* find component by glob **/<name>.{tsx, jsx} */ }

customRender(name:string){
  const Component = getComponentByName(name)

  render(() => <Component/>, element)
}

this way, when i edit any child component, hot reload works as expected, but when i make any change to the root component, i have no hot reload.

lxsmnsyc commented 7 months ago

@RsMan-Dev which one is the root component?

if it's the customRender, Solid Refresh doesn't cover it.

RsMan-Dev commented 7 months ago

i am using the builtin render, the root component is Component @lxsmnsyc

lxsmnsyc commented 7 months ago

@RsMan-Dev then it should work for the components in the your glob. unless it doesn't follow the requirements

RsMan-Dev commented 7 months ago

what are the requirement to follow to have them working? @lxsmnsyc

RsMan-Dev commented 7 months ago

can you help me @lxsmnsyc ?

Basically, glob is doing this:

globalThis.allComponents = import.meta.glob('/javascripts/components/**/*.{jsx,tsx,js,ts}', {eager: true});
// code produced by vite
import * as __glob__0_0 from './components/Home.tsx'
globalThis.allComponents = {
  './components/Home.tsx': __glob__0_0,
}

When i am rendering Home, it's simply rendering it like:

const Component = allComponents['./components/Home.tsx'].default

//native solidjs's render
render(() => <Component/>, root)

So, i'm basically using native solidjs functions, what is missing to have hot reload working on this code?

lxsmnsyc commented 7 months ago

All of the code you showed are not covered by Solid Refresh.

Show me your Home component and I can give a definite answer.

RsMan-Dev commented 7 months ago

it's hello, not home on my code:

import { createSignal } from "solid-js";

export default function Hello() {
  const [count, setCount] = createSignal(0);
  return (
    <div>
      <button onClick={() => setCount(count() + 1)}>count: {count()}</button>
    </div>
  );
}
RsMan-Dev commented 7 months ago

when this code is used inside another component, it's hot reloaded like expected.

lxsmnsyc commented 7 months ago

Then that should work. There's nothing to handle in your root file.

RsMan-Dev commented 7 months ago

another simple reproduction form me:

components/Hello.tsx

import { createSignal } from "solid-js";
import Sub from "./Sub";

export default function Hello() {
  const [count, setCount] = createSignal(0);
  return (
    <div>
      <Sub/>
      <br/>
      <button onClick={() => setCount(count() + 1)}>count: {count()}</button>
    </div>
  );
}

components/Sub.tsx

import { createSignal } from "solid-js";

export default function Sub() {
  const [count, setCount] = createSignal(0);
  return (
    <div>
      <button onClick={() => setCount(count() + 1)}>count: {count()}</button>
    </div>
  );
}

root.ts

import Hello from "./components/Hello";
render(Hello, this)

Here, only Sub is hot reloaded, not Hello, the root component.

lxsmnsyc commented 7 months ago

So what behavior does Hello show when making changes?

RsMan-Dev commented 7 months ago

nothing changind

RsMan-Dev commented 7 months ago

vite is trying to hot reload, i receive something on network, but nothing happen in frontend. idk if it's changing anything, but render is called inside a custom element, on it's "connectedCallback" function.

RsMan-Dev commented 7 months ago

that's why i'm using "this" as root element

RsMan-Dev commented 7 months ago

i succeeded to make hot reloading working using this workaround:

components/Root.tsx

interface RootProps { Component: any; props: Record<string, any>;}
export default function Root({Component, props}: RootProps) {
  return <>
    <Component {...props}/>
  </>;
}

components/Hello.tsx

//normal component

root.ts

render(() => <Root Component={component} props={props}/>, this)

here, home is hot reloaded as expected, because not the root component, waiting for your potential fix, i will work using this method.

lxsmnsyc commented 7 months ago

I don't really understand the issue.

Can you perhaps just provide a repro?

RsMan-Dev commented 7 months ago

When the component is directly rendered using render(), it becomes impossible to hot reload, but when the component is rendered by another component, it becomes hot reloadable