Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

187
Views
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 answers
Answer question

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!