denoland / fresh

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

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

Closed adamzerner closed 10 months ago

adamzerner commented 10 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 10 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 10 months ago

Oh, I see. Thanks for clarifying.