Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

189
Visualizações
How to create a nested react componet?

I have a dropdown component. Which will have 2 props.

  1. trigger (which will trigger the dropdown)
  2. list (the dropdown list content)

Here is my component:

import { useLayer } from "react-laag";
import { ReactElement, useState } from "react";
import classNames from 'classnames';

interface Props {
    trigger?: string | ReactElement
    children?: ReactElement | Array<ReactElement>
    className?: string
}

const Dropdown = ({ trigger, children, className }: Props) => {
    const [isOpen, setOpen] = useState(false);

    // helper function to close the menu
    function close() {
        setOpen(false);
    }

    const { renderLayer, triggerProps, layerProps } = useLayer({
        isOpen,
        onOutsideClick: close, // close the menu when the user clicks outside
        onDisappear: close, // close the menu when the menu gets scrolled out of sight
        overflowContainer: true, // keep the menu positioned inside the container
        auto: true, // automatically find the best placement
        placement: "bottom-end", // we prefer to place the menu "top-end"
        triggerOffset: 12, // keep some distance to the trigger
        containerOffset: 16, // give the menu some room to breath relative to the container
        arrowOffset: 16 // let the arrow have some room to breath also
    });

    // Again, we're using framer-motion for the transition effect
    return (
        <div className='dropdown' >
            <button className='dropdown-trigger' {...triggerProps} onClick={() => setOpen(!isOpen)}>
                {* I want to render trigger here *}
            </button>
            {isOpen &&
                renderLayer(
                    <div className={classNames(['dropdown-list', className])} {...layerProps}>
                        {* I want to render list here *}
                    </div>
                )}
        </div>
    );
}

export default Dropdown

Here I am using react-lagg for the dropdown.

I want to use this component like this:

<Dropdown>
   <Dropdown.Trigger>
    <div>Some JSX content here</div>
   </Dropdown.Trigger>
   <Dropdown.List>
    <div>Some JSX content here</div>
   </Dropdown.List>
</Dropdown>

How can I implement this patter on react?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Basically if you want to use that component that way, try this. **I will write it in JS

const Dropdown = ({ children }) => {
  return <div className="dropdown">{children}</div>;
};

const Trigger = (triggerProps) => (
  <button className="dropdown-trigger" {...triggerProps}>
    {triggerProps.children}
  </button>
);
const List = (listProps) => (
  <div className="dropdown-list" {...listProps}>
    {listProps.children}
  </div>
);

Dropdown.Trigger = Trigger;
Dropdown.List = List;

export default Dropdown;

In your case, Dropdown.Trigger is triggering state from Dropdown. I'm not sure it's the best practice, you could write this way

import React, { useState, cloneElement } from 'react';
import classNames from 'classnames';

const Trigger = (triggerProps) => (
  <button className="dropdown-trigger" {...triggerProps}>
    {triggerProps.children}
  </button>
);
const List = ({ className, ...listProps }) => (
  <div className={classNames(['dropdown-list', className])} {...listProps}>
    {listProps.children}
  </div>
);

const Dropdown = ({ trigger, children, className }) => {
  const [isOpen, setOpen] = useState(false);

  return (
    <div className="dropdown">
      {cloneElement(
        children.find(({ type }) => type === Trigger),
        {
          onClick: () => setOpen(!isOpen),
        }
      )}
      {isOpen &&
        cloneElement(
          children.find(({ type }) => type === List),
          {
            className: className,
          }
        )}
    </div>
  );
};

Dropdown.Trigger = Trigger;
Dropdown.List = List;

export default Dropdown;

will be used like this

<Dropdown className="test">
  <Dropdown.Trigger>trigger</Dropdown.Trigger>
  <Dropdown.List>list</Dropdown.List>
</Dropdown>

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda