5

New to react and cannot find a quick answer in the many simple examples out there. Gatsby and React generate class names at run time so my class .page1 in scss ends up being sections-module--page1--2SNjF.

What is the correct way to select an element and add an additional class to it?

import React from 'react';
import styles from '../scss/sections.module.scss';
import $ from 'jquery';

class Section extends React.Component {
    componentDidMount() {
       $(what??).addClass('active'); // how to select .page1 here
    }

    render() {
        return (
            <>
                <section className={styles.page1}>
                    <h2>section 1</h2>
                </section>
                <section className={styles.page2}>
                    <h2>section 2</h2>
                </section>
            </>
        )
    }
}

export default () => (
    <Section/>
)
Samuel Goldenbaum
  • 18,391
  • 17
  • 66
  • 104
  • Good joke ;) In react you can do it in many ways: https://stackoverflow.com/questions/30533171/react-js-conditionally-applying-class-attributes https://stackoverflow.com/questions/51809623/react-switching-between-lists-with-same-class/51810348#51810348 – xadm Aug 18 '18 at 13:53
  • Those posts do not cover the conditional class assignment with CSS modules which has to be handled differently. The principles are the same but the referencing is different which is the confusing part. @Chev do either of these answers help you? – dysfunc Aug 19 '18 at 18:03

1 Answers1

2

You don't need jQuery for this and should avoid mixing the two.

Try this out. You'll need to create a ref to the element so you can access it.

import React, { Component } from 'react';
import styles from '../scss/sections.module.scss';

class Section extends Component {
  constructor(props) {
    super(props);

    this.firstSection = React.createRef();
  }

  componentDidMount() {
    this.firstSection.classList.add(`${styles.page1} ${styles.active}`);
  }

  render() {
    return (
      <div>
        <section ref={this.firstSection}>
          <h2>section 1</h2>
        </section>
        <section className={styles.page2}>
          <h2>section 2</h2>
        </section>
      </div>
    )
  }
}

export default Section;

Add the active class to your module style SCSS file in the proper place so that you can reference it correctly.

sections.module.scss

.page1,
.page2 {
  &.active {
     background: red; 
  }
}

You can also use the classnames lib

import React, { Component } from 'react';
import styles from '../scss/sections.module.scss';
import classnames from 'classnames';

class Section extends Component {
  constructor(props) {
    super(props);

    this.state = {
      activeSection: 1
    };
  }

  render() {
    const classes = classnames(styles.page1, {
      [styles.active]: this.state.activeSection === 1
    });

    return (
      <div>
        <section className={classes}>
          <h2>section 1</h2>
        </section>
        <section className={styles.page2}>
          <h2>section 2</h2>
        </section>
      </div>
    )
  }
}

export default Section;
dysfunc
  • 2,008
  • 1
  • 13
  • 15
  • looking at the first example above, the reference to the active style is incorrect. the `.active` style is not in the root of the scss, but nested within the parent `.page` so this actually cannot work unless `.active` is not nested – Samuel Goldenbaum Aug 26 '18 at 02:29