ozanmuyes
ozanmuyes

Reputation: 806

How to self reference Astro component

I have this component Astro component (located at "src/components/Menu.astro");

---
export interface MenuItem {
  name: string;
  link: string;
  items?: MenuItem[];
}

export interface Props {
  items: MenuItem[];
  depth: number;
}

const { items, depth } = Astro.props;
---

<ul data-depth={depth}>
  {
    items.map(({ name, link, items: subItems }) => {
      if (subItems && subItems.length > 0) {
        return (
          <li>
            <div class="dropdown">
              {link ? <a href={link}>{name}</a> : <button>{name}</button>}

              <Menu items={subItems} depth={depth + 1} />
            </div>
          </li>
        );
      }

      return (
        <li>
          <a href={link}>{name}</a>
        </li>
      );
    })
  }
</ul>

On line 28 (where the line reads <Menu items={subItems} depth={depth + 1} />) an error thrown saying;

ReferenceError: Menu is not defined

How can I self reference an Astro component in this case? Thanks in advance.

PS: "Menu" is the component file's name.

Upvotes: 2

Views: 2945

Answers (2)

Bryce Russell
Bryce Russell

Reputation: 1360

Astro has a built in method for this called Astro.self that you can use Astro.self

Example from docs:

---
const { items } = Astro.props;
---
<ul class="nested-list">
  {items.map((item) => (
    <li>
      <!-- If there is a nested data-structure we render `<Astro.self>` -->
      <!-- and can pass props through with the recursive call -->
      {Array.isArray(item) ? (
        <Astro.self items={item} />
      ) : (
        item
      )}
    </li>
  ))}
</ul>

Upvotes: 11

einarmagnus
einarmagnus

Reputation: 3590

In the front-matter, i.e. between the two ---, you write import Menu from "./Menu.astro".

You'll get new errors, as you can't use statements in the body.

Change

items.map(({ name, link, items: subItems }) => {
      if (subItems && subItems.length > 0) {
        return (
          <li>
            <div class="dropdown">
              {link ? <a href={link}>{name}</a> : <button>{name}</button>}

              <Menu items={subItems} depth={depth + 1} />
            </div>
          </li>
        );
      }

      return (
        <li>
          <a href={link}>{name}</a>
        </li>
      );
    })

to

items.map(({ name, link, items: subItems }) => 
      (subItems && subItems.length > 0)
        ? <li>
            <div class="dropdown">
              {link ? <a href={link}>{name}</a> : <button>{name}</button>}

              <Menu items={subItems} depth={depth + 1} />
            </div>
          </li>

       : <li>
          <a href={link}>{name}</a>
        </li>
    )

Upvotes: 1

Related Questions