Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: allow to use reactive markup generators inside web-components #44

Merged
merged 7 commits into from
Jan 8, 2024

Conversation

aralroca
Copy link
Collaborator

@aralroca aralroca commented Jan 8, 2024

Fixes: #43
Related with #152

DOCS:


Reusing Elements without Shadow DOM

In Brisa, incorporating components using the syntax <Component /> within a web component is not feasible. This invocation method is exclusive to server components. Brisa follows this approach to maintain a clear separation of concerns, where client components solely contain client code, and server components house server code, along with the markup of the web-components and other elements like a div.

  • <Component /> - Smart/dummy server component.
  • <web-component /> - Smart web component element. Dummy versions can be created, but it's advisable to leverage server components to avoid client-side JavaScript or use markup generators inside.
  • {markupGenerator()} - Generates dummy markup within web-server components.

Efforts have been invested in facilitating communication between these two realms, ensuring a seamless integration without confusion from intermingling code.

Concepts:

  • Smart: Possesses an internal state.
  • Dummy: Can utilize external state, but lacks a state created and housed internally.

This distinctive approach distinguishes Brisa from other frameworks in reusing web component code without necessitating the creation of shadow DOM.

In frameworks like React, to reuse markup (HTML elements), dummy components must be created—components without state. However, in Brisa, it is recommended to employ markup generators (functions) and invoke them during rendering.

import { type Signal } from "brisa";

function generatePercentage(percentage: Signal<number>) {
  return (
    <span>
      Percentage:{" "}
      {percentage.value > 0 ? `+${percentage.value}` : percentage.value}%
    </span>
  );
}

Subsequently, these markup generators can be directly invoked within JSX:

import { type WebContext } from "brisa";
import generatePercentage from "./@-partials/generate-percentage";

export default function Counter({}, { state }: WebContext) {
  const count = state(0);

  return (
    <div>
      <button onClick={() => count.value++}>+</button>
      {generatePercentage(count)}
      <button onClick={() => count.value--}>-</button>
    </div>
  );
}

Markup generators execute only when the web component is mounted, and the content returned by the generator becomes reactive. However, an exception exists when the argument holds the value of a signal rather than the full signal.

Do this:

// ✅ Good: The content of the markup generator
// will be reactive as it consumes the signal. It
// won't execute generatePercentage again.
<div>{generatePercentage(count)}</div>

Avoid this:

// ❌ Bad: It will be reactive, but the
// generatePercentage markup generator will be
// executed again because the content only
// has the signal value and not the full signal.
<div>{generatePercentage(count.value)}</div>

Unlike web components, markup generators lack their own state.

Choosing between a web component and a markup generator depends on the need:

  • Use a web component if encapsulating logic in a state is required.
  • Use a markup generator if generating HTML for reuse in web components without internal state is sufficient.

Note

Performance concerns are alleviated in Brisa, as there are no rerenders, and markup generators execute only once.

Tip

You have the flexibility to establish directories or files with the @- prefix, steering clear of the need to create web components within the src/web-components directory. This proves beneficial when incorporating reusable markup generators within web components. The sole exception to this practice is @-native, a dedicated directory specifically designed for crafting native web components, free from both Brisa and JSX influences.

Caution

Avoid sending the WebContext or parts of them to the markup generators, you can send signals (props, state, derived, context and store signals) and static values without issues.

@aralroca aralroca requested review from amatiasq and danielart January 8, 2024 16:53
@aralroca aralroca self-assigned this Jan 8, 2024
@aralroca aralroca merged commit 17dbbf7 into main Jan 8, 2024
1 check failed
@aralroca aralroca deleted the markup-generators branch January 8, 2024 16:58
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

allow to use reactive markup generators inside web-components
1 participant