Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically Open and Close antd / react Collapse Component

I want to dynamically open/close Collapse Elements independent of user interaction (to reveal a specific panel via a search result).

The Collapse react component has setActiveKey (and uses it on user click) but it is not exposed to the Collapse Node reference.

Is there anyway to open or close in a way that will not trigger a re-render?

I tried using state and props, but this always re-renders the full tree of nested Collapse components, which in my case takes over 3 seconds.

Posting the full code would be excessive here as there are many interdependent components nested. However the basic structure is visible here: https://codesandbox.io/s/nk64q4xy8p

I want to open a specific panel via a different user interaction. In the codepen that would be onChange of the select or clicking the button.

like image 238
gotjosh Avatar asked Apr 12 '19 10:04

gotjosh


People also ask

How to use ant design collapse component in ReactJS?

We can use the following approach in ReactJS to use the Ant Design Collapse Component. accordion: It is used to collapse renders as Accordion if this value is set to true. activeKey: It is used to denote the key of the active panel.

How to expand and collapse a header in react?

There are multiple options for expanding and collapsing any header on the basis of varying requirement. By default we get a react accordion component where only one item can be expanded. In order to collapse this accordion, you need to expand another component.

What is the difference between the collapse component and buttons?

The collapse component is used to show and hide content. Buttons or anchors are used as triggers that are mapped to specific elements you toggle. Collapsing an element will animate the height from its current value to 0.

What is react nested collapse?

React Nested Collapse The final example of react collapse component consists of container within a toggle container. That means we can apply collapse action on child container for single collapse action or apply it directly to parent container for collapse all feature.


1 Answers

There is nothing bad to do it with state variable. Once state or props change, it will render the entire components and also the nexted ones.

But if there is any performance issue due to re-rendering, probably you should look into pure components and react lifecycle methods to improve the performance (or avoid re-render).

In addition, you can also use special props of Antd's Collapse destroyInactivePanel, it will destroy (unmount) inactive panels.

Code for your reference (https://codesandbox.io/s/y30z35p1vv?fontsize=14)

import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Collapse, Button, Select } from "antd";

const Panel = Collapse.Panel;
const text = `
  A dog is a type of domesticated animal.
  Known for its loyalty and faithfulness,
  it can be found as a welcome guest in many households across the world.
`;

class AvoidRenders extends React.Component {
  state = {
    openPanel: "1"
  };

  onChange = key => {
    this.setState({
      openPanel: key
    });
  };

  render = () => {
    return (
      <div>
        <Select
          dropdownMatchSelectWidth={false}
          defaultValue="1"
          onChange={this.onChange}
        >
          <Select.Option key="1" value="1">
            Panel 1
          </Select.Option>
          <Select.Option key="2" value="2">
            Panel 2
          </Select.Option>
          <Select.Option key="3" value="3">
            Panel 3
          </Select.Option>
        </Select>
        <Collapse activeKey={this.state.openPanel} destroyInactivePanel={true}>
          <Panel header="This is panel header 1" key="1">
            <Text1 />
          </Panel>
          <Panel header="This is panel header 2" key="2">
            <Text2 />
          </Panel>
          <Panel header="This is panel header 3" key="3">
            <Text3 />
          </Panel>
        </Collapse>
      </div>
    );
  };
}

class Text1 extends React.PureComponent {
  componentWillUnmount = () => {
    console.log("Destroyed 1");
  };
  componentWillUpdate = () => {
    console.log("Updated 1");
  };
  render = () => (
    <p>
      {console.log("Rendered 1")}
      {text}
    </p>
  );
}

class Text2 extends React.PureComponent {
  componentWillUnmount = () => {
    console.log("Destroyed 2");
  };
  componentWillUpdate = () => {
    console.log("Updated 2");
  };
  render = () => (
    <p>
      {console.log("Rendered 2")}
      {text}
    </p>
  );
}

class Text3 extends React.PureComponent {
  componentWillUnmount = () => {
    console.log("Destroyed 3");
  };
  componentWillUpdate = () => {
    console.log("Updated 3");
  };
  render = () => (
    <p>
      {console.log("Rendered 3")}
      {text}
    </p>
  );
}

ReactDOM.render(<AvoidRenders />, document.getElementById("container"));

I hope, this would help.

like image 173
Shreyans Shrivastav Avatar answered Oct 12 '22 14:10

Shreyans Shrivastav