Material Design Components Toggle effect not working

Viewed 320

Im trying to use material components IconButton with React.
Material Design : https://material-components.github.io/material-components-web-catalog/#/component/icon-button

It work and show element and do repple. But toggle doesnt work.
here is my code and element tree in devtool for chrome.
please teach me the solution.

import React, { useEffect } from 'react';
import { MDCIconButtonToggle } from '@material/icon-button';

const ButtonLike = () => {
  useEffect(() => {
    const iconToggle = new MDCIconButtonToggle(
      document.querySelector('.mdc-icon-button'),
    );
    iconToggle.on = true;
  });
  return (
    <button
      id="add-to-favorites"
      className="mdc-icon-button mdc-icon-button--on"
      aria-label="Add to favorites"
      aria-pressed="false"
    >
      <i className="material-icons mdc-icon-button__icon mdc-icon-button__icon--on">favorite</i>
      <i className="material-icons mdc-icon-button__icon">favorite_border</i>
    </button>
  );
};

export default ButtonLike;

element tree

<button id="add-to-favorites" class="mdc-icon-button mdc-icon-button--on" aria-label="Add to favorites" aria-pressed="false">
  <i class="material-icons mdc-icon-button__icon mdc-icon-button__icon--on">
    favorite
  </i>
  <i class="material-icons mdc-icon-button__icon">
    favorite_border
  </i>
</button>
1 Answers

You instantiate iconToggle inside useEffect(), but you overlooked the fact that useEffect() takes a 2nd argument, the deps list. Without it, that logic is re-run at every re-render, meaning your iconToggle.on is set back to true each time, thus it stays at "on".

As side note, a more React-ish way to select HTML element is by useRef(), instead of document.querySelector() which might find other unwanted element

import React, { useEffect, useRef } from 'react';
import { MDCIconButtonToggle } from '@material/icon-button';

const ButtonLike = () => {
  const buttonRef = useRef(null);

  useEffect(() => {
    const iconToggle = new MDCIconButtonToggle(buttonRef.current);
    iconToggle.on = true;
  }, []);  // <-- You need to pass in an empty array
           //     to signal that you want this logic to run only once.

  return (
    <button
      ref={buttonRef}
      id="add-to-favorites"
      className="mdc-icon-button mdc-icon-button--on"
      aria-label="Add to favorites"
      aria-pressed="false"
    >
  );
}
Related