denoland / fresh

The next-gen web framework.
https://fresh.deno.dev
MIT License
12.18k stars 623 forks source link

Bug: Reactivity not working for `() => <Stepper />` #2194

Closed adamzerner closed 8 months ago

adamzerner commented 9 months ago

Reproduction: https://github.com/adamzerner/reactivity-bug-demo

Clicking "increment" doesn't work. It doesn't increment the number. It doesn't even log "hits onClick". Somehow the reactivity is lost in ComponentDocsPage even though ComponentDocsPage is an island.

Relevant code:

routes/molecules/stepper.tsx

import { Stepper } from "../../islands/molecules/stepper.tsx";
import { ComponentDocsPage } from "../../islands/demo/component-docs-page.tsx";

export default () => {
  const sections = [{
    example: () => <Stepper />,
  }];

  // Works
  // return <Stepper />
  // return <div>{sections[0].example()}</div>;

  // Doesn't work
  return <ComponentDocsPage sections={sections} />;
};

islands/molecules/stepper.tsx

import { useState } from "preact/hooks";

export const Stepper = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <div>Count: {count}</div>
      <button
        onClick={() => {
          console.log("hits onClick");
          setCount((c) => c + 1);
        }}
      >
        increment
      </button>
    </div>
  );
};

islands/demo/component-docs-page.tsx

import { JSX } from "preact";

export const ComponentDocsPage = (
  { sections }: { sections: { example: () => JSX.Element }[] },
) => {
  return (
    <div>
      {sections[0].example()}
    </div>
  );
};
marvinhagemeister commented 9 months ago

Passing functions from the server to the browser is not possible. In the snippet the route file passes a function to an island as a prop. That won't work. Iirc we do already check if a prop itself is a function and display an error message, but we don't do so for nested objects like <MyIsland sections={ [{ example: () => {} }] } /> I think.

adamzerner commented 8 months ago

Oh, I see. Thanks for clarifying.