zougari47
zougari47

Reputation: 1

How to loop over <Slot /> in Qwik?

I'm trying to loop over <Slot /> in Qwik Component but the problem it's only render the first item. In Qwik docs: The Slot component can be used multiple times in the same component, as long as it has a different name property: But how I'm suppose to handle the name if I don't know the number of loop(dynamic).

marquee.tsx

import { cn } from '@/lib/utils'
import {
  Slot,
  component$,
  useVisibleTask$,
  type HTMLAttributes,
} from '@builder.io/qwik'

export type MarqueeProps = HTMLAttributes<HTMLDivElement> & {
  direction?: 'left' | 'up'
  pauseOnHover?: boolean
  reverse?: boolean
  fade?: boolean
  innerClassName?: string
  numberOfCopies?: number
}

export const Marquee = component$<MarqueeProps>(
  ({
    direction = 'left',
    pauseOnHover = false,
    reverse = false,
    fade = false,
    innerClassName,
    numberOfCopies = 5,
    ...props
  }) => {
    useVisibleTask$(() => {
      console.log({ numberOfCopies }) // 5
    })

    return (
      <div
        class={cn(
          'group flex gap-[1rem] overflow-hidden',
          direction === 'left' ? 'flex-row' : 'flex-col',
          props.class,
        )}
        style={{
          maskImage: fade
            ? `linear-gradient(${
                direction === 'left' ? 'to right' : 'to bottom'
              }, transparent 0%, rgba(0, 0, 0, 1.0) 10%, rgba(0, 0, 0, 1.0) 90%, transparent 100%)`
            : undefined,
          WebkitMaskImage: fade
            ? `linear-gradient(${
                direction === 'left' ? 'to right' : 'to bottom'
              }, transparent 0%, rgba(0, 0, 0, 1.0) 10%, rgba(0, 0, 0, 1.0) 90%, transparent 100%)`
            : undefined,
        }}
        {...props}>
        {Array(numberOfCopies)
          .fill(0)
          .map((_, i) => (
            <div
              key={i}
              class={cn(
                'flex shrink-0 justify-around gap-[1rem] [--gap:1rem]',
                direction === 'left'
                  ? 'animate-marquee-left flex-row'
                  : 'animate-marquee-up flex-col',
                pauseOnHover && 'group-hover:[animation-play-state:paused]',
                reverse && 'direction-reverse',
                innerClassName,
              )}>
              <Slot />
            </div>
          ))}
      </div>
    )
  },
)

hello.tsx

import { component$ } from '@builder.io/qwik'
import { Marquee } from './ui/marquee'

export const Hello = component$(() => {
  return (
    <div class='h-screen w-full border border-gray-500'>
      <p>I'm Qwik component</p>

      <Marquee class='h-full border-4 border-green-900 [--duration:5s]'>
        <div class='h-20'>Hello </div>
        <div class='h-20'>Hola</div>
        <div class='h-20'>Bonjour</div>
      </Marquee>
    </div>
  )
})

I was expecting to render the children(Slot) multiple time. screenshot

Upvotes: 0

Views: 88

Answers (1)

Tob
Tob

Reputation: 963

It’s just not possible.

If you need the children, you can have a prop JSXNode or pass data and build the children in the component.

The whole idea of this mechanism is separation.

<Component yourSlot={<p>hello</p>} />

The slot is a placeholder and remembering the source code it picks exactly one spot and after render it’s over.

Keep in mind slot is not just there for one element.

Upvotes: 0

Related Questions