【问题标题】:Dynamically Open and Close antd / react Collapse Component动态打开和关闭 antd/react 折叠组件
【发布时间】:2019-09-03 01:57:59
【问题描述】:

我想独立于用户交互动态打开/关闭折叠元素(通过搜索结果显示特定面板)。

Collapse 反应组件具有 setActiveKey(并在用户单击时使用它),但它不会暴露给 Collapse Node 引用。

有没有办法以不会触发重新渲染的方式打开或关闭?

我尝试使用 state 和 props,但这总是重新渲染嵌套 Collapse 组件的完整树,在我的情况下需要 3 秒以上。

在这里发布完整的代码是多余的,因为嵌套了许多相互依赖的组件。但是基本结构在这里可见:https://codesandbox.io/s/nk64q4xy8p

我想通过不同的用户交互打开特定面板。在选择或单击按钮的 onChange 代码笔中。

【问题讨论】:

  • 你为什么不尝试把函数放在 setTimeout 中?
  • 请发布您的代码以更好地帮助您。编辑您的问题并包含最小、完整和可验证示例的所有必需信息。
  • 我添加了一个 codepen 示例,说明我想对嵌套结构做些什么,但是要在此处(甚至在 codepen 上)发布太多代码以使真正的用例可见:12 个月,每个有 5-20 个事件,每个事件还可以折叠成一个由 3 个面板组成的内部手风琴。
  • @ThanveerShah 你指的是哪个函数?
  • 所以你想一键打开所有面板?

标签: javascript reactjs antd


【解决方案1】:

使用状态变量没有什么不好的。一旦 state 或 props 发生变化,它将渲染整个组件以及下一个组件。

但是如果由于重新渲染而出现任何性能问题,可能您应该查看 pure components 并做出反应 lifecycle methods 以提高性能(或避免重新渲染)。

此外,你还可以使用 Antd 的 Collapse destroyInactivePanel 的特殊道具,它会销毁(卸载)非活动面板。

供您参考的代码 (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"));

我希望,这会有所帮助。

【讨论】:

  • 谢谢!我调整了你的沙箱:codesandbox.io/embed/n3zl5yyz7m,以便:1)我可以点击展开/折叠手风琴并从选择中控制 2)我可以控制破坏道具 3)所有三个面板都在第一次渲染时强制渲染......现在,我似乎没有得到销毁和渲染(即使开关打开) - 但我得到了整个组件的重新渲染
  • 它不会破坏,因为您使用的是“forceRender”。无论如何,更新 activeKey 总是会重新渲染整个组件。可以做的最好的事情是避免重新渲染子组件(使用纯组件)。如果渲染中有任何耗时超过 3 秒的繁重逻辑,请将其移至其他地方。如果你真的想要一个方法。使用纯 css 手风琴codepen.io/raubaca/pen/PZzpVe,如果您可以分享您的代码,我可以提供更多帮助。
  • 非常感谢您的帮助和提议!我找到了一个使用 shouldComponentUpdate() 和一次性 forceRender 的解决方案,以确保子组件在启动时可用,但不会在每次折叠/展开时呈现...
  • 实际上这个答案的第一行是我问题的很大一部分:“它将渲染整个组件”......我能够强制渲染一次并避免在这里重新渲染整个树: codesandbox.io/embed/n3zl5yyz7m 但我仍然不满意当我想更改内部组件的状态时需要渲染整个组件...
猜你喜欢
  • 1970-01-01
  • 2020-05-22
  • 1970-01-01
  • 1970-01-01
  • 2020-09-16
  • 1970-01-01
  • 2019-10-06
  • 2021-11-19
  • 2023-04-03
相关资源
最近更新 更多