atomicojs / atomico

Atomico a micro-library for creating webcomponents using only functions, hooks and virtual-dom.
https://atomicojs.dev
MIT License
1.15k stars 43 forks source link

Fragments not working #93

Closed efoken closed 1 year ago

efoken commented 1 year ago

Describe the bug I always wanted to report this since a long time. Fragments cannot be used in JSX like they can in React.

Example:

<>
  <div>Fragment example</div>
</>

See: https://reactjs.org/docs/fragments.html

I guess the JSX runtime needs to export a Fragment symbol to make this work.

To Reproduce Steps to reproduce the behavior:

  1. Setup an Atomico project with TypeScript
  2. Try to use fragments <> in JSX

Expected behavior Fragments can be used in JSX. And maybe context Providers can render a fragment instead of an element?

Additional context We currently always use <div> elements with style={{ display: 'contents' }} to work around this.

UpperCod commented 1 year ago

Fragment Support

Thanks for reminding me, internally Atomico works with fragments, but there is no tag that allows its use at the JSX level, I will work to add it in the next version of Atomico.

About Providers and Fragments

Fragments can be used in JSX. And maybe context Providers can render a fragment instead of an element?

Atomico does not have a system of synthetic components to allow this type of behavior. In Atomico the Provider instance will create a listener to synchronize the nested components with the value given to Provider, any update on the provider value will be communicated directly to the component, this behavior has better performance since Atomico does not need to scan the entire tree of the virtualDOM to propagate the new value, this behavior allows the Atomico Context to work even outside of Atomico, example:

<MyContextProviderWithAtomico>
  <MyAppWithReact>
    <MyAppWithAtomico></MyAppWithAtomico>
  </MyAppWithReact>
</MyContextProviderWithAtomico>

I'm going to document this, to share the new possibilities with the Atomico Context API and the differences with the React API

I invite you to share questions or ideas that you would like to see in the documentation about the Context API

efoken commented 1 year ago

Yeah I see, I already read your code and thought that it's not possible that Providers render Fragments – clearly 😄

But then just in my opinion it would be really good to have the option to apply styles to Providers, or even change it internally to give it display: contents, because (at least for us) this is important, because we are using flexbox layouts for everything and unstyled elements can destroy the layout.

For example when using flex-direction: row on the parent element, all children should be rendered in a row, but when the children are wrapped within a Provider it does not work anymore.

The <slot> element also has display: contents by default in all Browsers in order to make it not destroying layouts.

UpperCod commented 1 year ago

Hi @efoken the fragment tag (<></>) is already available in atomico@1.63.0 at the jsx-runtime level, example:

<host>
    {data.map(() => (
        <>
            <h1>header</h1>
            <h1>content</h1>
        </>
    ))}
</host>
efoken commented 1 year ago

Nice, thank you 🙏 I saw it in the jsx-runtime.js, but the export is missing in atomico package and I think TypeScript types are missing!?

import { Fragment } from 'atomico';

Module '"atomico"' has no exported member 'Fragment'.ts(2305)

UpperCod commented 1 year ago

Thanks for noticing, as you mentioned, it is necessary to export as a type for typescript, I have fixed it in atomico@1.63.1