You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React-Materialize折叠面板程序化展开与回调无限循环问题

React-Materialize Collapsible: Programmatic Expansion & Fixing Infinite Loops

Hey there! Let's tackle your two questions about React-Materialize's Collapsible component—first fixing that frustrating infinite loop, then covering how to expand items programmatically.

Fixing the "Maximum update depth exceeded" Error

The root cause of your infinite loop is how you're passing the onClick (or onSelect) handler. Right now, you're directly invoking the function instead of passing a callback reference:

// ❌ Bad: This calls changeBoardType immediately on every render
<CollapsibleItem onClick={this.changeBoardType("single")} />

Every time your component renders, this.changeBoardType("single") runs, triggers a setState, which forces another render—and the cycle repeats infinitely.

Solutions:

There are three clean ways to fix this:

  1. Wrap the call in an arrow function
    This ensures the function only runs when the click/select event fires:

    <CollapsibleItem onClick={() => this.changeBoardType("single")} header='Single Hand' />
    
  2. Use a data attribute + bound handler
    If you prefer to avoid inline arrow functions (for minor performance gains in large lists), bind your handler in the constructor and use a data attribute to pass the value:

    class YourComponent extends React.Component {
      constructor(props) {
        super(props);
        this.handleCollapseSelect = this.handleCollapseSelect.bind(this);
      }
    
      handleCollapseSelect(event) {
        const type = event.currentTarget.dataset.type;
        this.changeBoardType(type);
      }
    
      render() {
        return (
          <Collapsible accordion>
            <CollapsibleItem 
              onSelect={this.handleCollapseSelect} 
              data-type="single"
              header='Single Hand'
            >
              {/* ... */}
            </CollapsibleItem>
          </Collapsible>
        );
      }
    }
    
  3. Make changeBoardType return a function
    Adjust your changeBoardType method to return a callback function instead of executing immediately:

    changeBoardType = (type) => () => {
      this.setState({ boardType: type });
      // Your other logic here
    }
    
    // Then use it like this:
    <CollapsibleItem onClick={this.changeBoardType("single")} />
    

All three approaches will stop the immediate function invocation and prevent the infinite loop.

Programmatic Expansion of Collapsible Items

React-Materialize's Collapsible is built on top of Materialize CSS's vanilla JS component, so we can use its API to control expansion programmatically. Here's how:

Step 1: Add a ref to the Collapsible component

First, create a ref to access the underlying DOM element:

class YourComponent extends React.Component {
  constructor(props) {
    super(props);
    this.collapsibleRef = React.createRef();
    this.collapsibleInstance = null;
  }
}

Step 2: Initialize the Collapsible instance

In componentDidMount, initialize the Materialize Collapsible instance using the ref:

componentDidMount() {
  // Initialize the Collapsible with any options you need
  this.collapsibleInstance = M.Collapsible.init(this.collapsibleRef.current, {
    accordion: true // Match your existing accordion setting
  });
}

Step 3: Use the instance methods to expand/collapse

Materialize's Collapsible instance has open() and close() methods that take an item index (starting at 0) as an argument. You can call these methods anywhere in your component:

// Expand the first item (index 0)
expandFirstItem = () => {
  this.collapsibleInstance.open(0);
};

// Collapse the second item (index 1)
collapseSecondItem = () => {
  this.collapsibleInstance.close(1);
};

Step 4: Attach the ref to your Collapsible

Finally, link the ref to your Collapsible component in the render method:

render() {
  return (
    <>
      {/* Example button to trigger programmatic expansion */}
      <button onClick={this.expandFirstItem}>Open Single Hand Panel</button>

      <Collapsible accordion ref={this.collapsibleRef}>
        <CollapsibleItem header='Single Hand' icon='filter_1'>
          {/* ... */}
        </CollapsibleItem>
        {/* Other CollapsibleItems */}
      </Collapsible>
    </>
  );
}

For Function Components (React Hooks)

If you're using function components, the logic is similar but uses useRef and useEffect:

import { useRef, useEffect } from 'react';

function YourComponent() {
  const collapsibleRef = useRef(null);
  let collapsibleInstance = null;

  useEffect(() => {
    if (collapsibleRef.current) {
      collapsibleInstance = M.Collapsible.init(collapsibleRef.current, { accordion: true });
    }

    // Cleanup on unmount
    return () => {
      if (collapsibleInstance) {
        collapsibleInstance.destroy();
      }
    };
  }, []);

  const expandFirstItem = () => {
    collapsibleInstance.open(0);
  };

  return (
    <>
      <button onClick={expandFirstItem}>Open Single Hand Panel</button>
      <Collapsible accordion ref={collapsibleRef}>
        {/* ... */}
      </Collapsible>
    </>
  );
}

内容的提问来源于stack exchange,提问作者seanEd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:14:43