Cannot reference method with 'this' inside <StaticQuery /> with Gatsby

Seems I can reference this method everywhere but within the <StaticQuery /> component.

How can I reference the methods I try to mention in onMouseEnter and onMouseLeave ?

The error I’m getting is TypeError: Cannot read property 'collapseOpen' of undefined

import React, { Component } from "react"

import { StaticQuery, graphql } from "gatsby"

import * as bootstrap from 'bootstrap'

export default class Navigation extends Component {
  constructor(props) {
    super(props);
    this.collapseOpen = this.collapseOpen.bind(this)
    this.collapseClose = this.collapseClose.bind(this)
  }

  collapseOpen() {
    this.children[0].setAttribute('aria-expanded', 'true');
    this.children[0].classList.remove('collapsed');
    new bootstrap.Collapse(
      this.children[1],
      { toggle: true }
    );
  }

  collapseClose() {
    this.children[0].setAttribute('aria-expanded', 'false');
    this.children[0].classList.add('collapsed');
    new bootstrap.Collapse(
      this.children[1],
      { toggle: true }
    );
  }

  render () {
    var navData = {};
    return (
      <StaticQuery
        query={graphql`
          query NavQuery {
            allMarkdownRemark(
              sort: {fields: [frontmatter___tags, frontmatter___chapter], order: DESC}
            ) {
              edges {
                node {
                  id
                  frontmatter {
                    path
                    chapter
                    title
                    date
                    tags
                    chapter
                    chapter_path
                    chapter_type
                  }
                }
              }
            }
          }
        `}
        render={nav => (
          <>
            {nav.allMarkdownRemark.edges.map(function(post, index) {
              //throw new Error("my error message");
              if(post.node.frontmatter.chapter) {
                if(!navData[post.node.frontmatter.chapter]) {
                  navData[post.node.frontmatter.chapter] = {};
                  navData[post.node.frontmatter.chapter]['path'] = post.node.frontmatter.chapter_path;
                }
                if(!navData[post.node.frontmatter.chapter]['children']) {
                  navData[post.node.frontmatter.chapter]['children'] = {};
                }
                navData[post.node.frontmatter.chapter]['children'][post.node.frontmatter.title] = post.node.frontmatter.path;
              }else{
                navData[post.node.frontmatter.title] = {};
                navData[post.node.frontmatter.title]['path'] = post.node.frontmatter.path;
              }
            })}
            <aside class="bd-sidebar">
              <nav class="collapse bd-links" id="bd-docs-nav" aria-label="Docs navigation">
                <ul class="list-unstyled mb-0 py-3 pt-md-1">

                  {Object.keys(navData).map(function(key) {
                    if (navData[key]['children']!==undefined) {
                      return (
                        <li 
                          class="mb-1"
                          data-bs-target={'#'+key.replaceAll(' ', '-').toLowerCase()}
                          onMouseEnter={this.collapseOpen}
                          onMouseLeave={this.collapseClose}
                          aria-expanded="false"
                          data-bs-toggle="collapse">
                          <a
                            href={navData[key]['path']}
                            class="btn d-inline-flex align-items-center rounded collapsed text-start"
                            id={key.replaceAll(' ', '-').toLowerCase()+'-source'}>
                            {key}
                          </a>
                          <div class="collapse" id={key.replaceAll(' ', '-').toLowerCase()}>
                            <ul class="list-unstyled fw-normal pb-1 small">
                              {Object.keys(navData[key]['children']).map(function(innerKey) {
                                return (
                                  <li><a href={navData[key][innerKey]} class="d-inline-flex align-items-center rounded">{innerKey}</a></li>
                                )
                              })}
                            </ul>
                          </div>
                        </li>
                      )
                    } else {
                      return (
                        <li class="mb-1">
                          <a
                            href={navData[key]['path']}
                            class="d-inline-flex align-items-center rounded text-start"
                            id={key.replaceAll(' ', '-').toLowerCase()+'-source'}>
                            {key}
                          </a>
                        </li>
                      )
                    }   
                  })}
        
                </ul>
              </nav>
            </aside>
          </>
        )}
      />
    )
  }
}

I’m using Gatsby with Bootstrap 5.

I could be wrong but it looks like collapseOpen & collapseClose is a prop on the component so to reference it I would try:

onMouseEnter={this.props.collapseOpen}
onmouseLeave={this.props.collapseClose}
1 Like

That didn’t work. Didn’t come up with a solution so I just decided to refactor it functionally.

1 Like