【问题标题】:ReactJs how to know when a component is removed from DOMReactJs 如何知道组件何时从 DOM 中删除
【发布时间】:2016-11-24 13:49:01
【问题描述】:

我目前遇到了 React 的问题。我需要知道组件何时从 DOM 中移除。

我在组件生命周期中发现的只有 componentWillUnmount,它在组件从 DOM 中移除之前被调用。

有什么方法可以通过 React 实现这一点吗? 在纯 JavaScript 中?

谢谢。

[编辑]

@jpdelatorre “纯 javascript” === 不使用库 ;-)

我的用例是在 react 组件中使用 jsPlumb。

jsPlumb 基本上是一个在 DOM 中绘制 svg 并进行位置计算的库。

在我的主要组件中有一个项目列表。 每个项目都是一个组件。 在每个渲染的项目上,我使用 JsPlumb 来绘制它。

但是...当我删除列表中的一个项目时,这些项目正在改变 DOM 中的位置,所以我需要要求 jsPlumb 根据新位置重绘事物。所以这就是为什么我需要知道组件何时从 DOM 中完全移除。

【问题讨论】:

  • 您能否稍微扩展您的问题...也许提供您的用例为什么要这样做。 “纯 JavaScript”是什么意思?不使用图书馆?不使用 ES6 功能?
  • @jpdelatorre 请参阅我的Edit 了解更多信息

标签: javascript reactjs


【解决方案1】:

componentWillUnmount 是正确的生命周期方法。正如您所说,它是在组件被删除之前触发的。如果您有需要等到它被删除的东西,您可以使用带有短超时值的setTimeout 来安排当前任务完成后的回调。

【讨论】:

  • 感谢您的回答。设置超时是我目前正在做的......我一直在寻找一个“更清洁”的解决方案,但谢谢!
  • @pitrackster:据我所知,没有。我可以在 React 源代码中找到对 componentWillUnmount 的调用的唯一位置,然后实际卸载它,没有干预返回给浏览器,也没有进一步调用组件。
【解决方案2】:

componentWillUnmount 是可以被 hook 的生命周期方法。

但如前所述,如果您想在 component1 中了解有关卸载 component2 的信息,那么您需要在 component2 的生命周期方法中触发一个操作,该操作应在 component1 中订阅并在 component1 监听器中执行一些操作。

【讨论】:

  • 是的,我现在就是这样处理的,有一个超时......我从每个人的回答中看到没有其他解决方案......
  • 为什么超时?您可以通过订阅由另一个组件触发的事件来实现。
  • componentWillUnmount 不会告诉我组件何时真正从 DOM 中删除,但会说“嘿,我将被删除...迟早” ...这就是为什么我需要使用超时...因为我需要在组件消失后做一些事情!
【解决方案3】:

正如其他已经提到的,您需要componentWillUnmount。 这是 React 中的一个简单示例(我在其中添加了一些注释以了解正在发生的事情):

var Button = React.createClass({
  componentWillUnmount: function(){
      // console will show this message when compoent is being Unmounted("removed")
        console.log('Button removed');
  },

  render() {
    return <h1 ref='button_node'>
    <ReactBootstrap.Button bsStyle="success">Red</ReactBootstrap.Button>
    </h1>;
  }
});  



var RemoveButton = React.createClass({
  getInitialState: function() {
     // this state keep tracks if Button removed or not
     //(you can use it for some redrawing or anything else in your code)
     return {buttonMounted: true}
  },

  mountRedButton: function(){
    ReactDOM.render(<Button/>, document.getElementById('button'));
    this.setState({buttonMounted: true});
  },

  unmountRedButton: function(){
    ReactDOM.unmountComponentAtNode(document.getElementById('button'));
    this.setState({buttonMounted: false});
  },

  render() {
    return <h1>
      //based on condition if Button compoennt removed or not we show/hide different buttons
      { this.state.buttonMounted ? <ReactBootstrap.Button onClick={this.unmountRedButton } bsStyle="danger">Remove Red Button!</ReactBootstrap.Button> : null}
      { this.state.buttonMounted ? null :<ReactBootstrap.Button onClick={this.mountRedButton } bsStyle="success">Add Red Button!</ReactBootstrap.Button> }        
    </h1>;
  }
});


// mount components    
ReactDOM.render(<Button/>, document.getElementById('button'));
ReactDOM.render(<RemoveButton/>, document.getElementById('remove'));

这是JSFiddle上的完整工作示例

关于“plain javascript”——你已经在使用 React JS,我的例子是基于 React 和 ReactDom,仅此而已(实际上还有 react-bootstrap,我只为漂亮的按钮添加了它,它不是必需的全部)

更新: MutationObserver 的使用怎么样?如果您需要一段时间来删除 DOM 中的节点,但在删除节点之前触发 componentWillUnmount(这对您来说似乎不合适),您可以使用它。按照我的按钮示例:

var removalWatcher = new MutationObserver(function (e) {
    var removalTimeStamp = '[' + Date.now() + '] ';
  if (e[0].removedNodes.length) {
    console.log('Node was removed', e[0].removedNodes, 'timestamp:', removalTimeStamp)
  };
});

这是一个JsFiddle 更新示例。您可以比较 MutationObserver 和 React ComponentWillUnmount 打印到控制台的时间戳。

【讨论】:

  • 感谢您的详细解答。不幸的是,它不能解决我的问题。如果我想等待从 DOM 中删除“红色按钮”,我需要使用任意时间的超时……这在 IMO 中不可靠……但似乎没有其他办法……
  • @pitrackster 你能解释更多吗?什么时候需要活动?何时移除按钮,之前还是之后?
  • 对不起,我没有看到 unmountComponentAtNode 部分...但我不能使用它,因为我正在循环数据以呈现我的组件...我需要知道按钮何时被删除DOM
【解决方案4】:

好的,谢谢大家!我找到了一个适合我需要并且(恕我直言)干净的解决方案......

在我的父组件中,我处理 componentDidUpdate 生命周期事件,并且在那里我可以知道(使用 prevProps 和 props)所做的更改是否需要触发我的操作...

class MyComponent extends Component {
    // this one is called each time any props is changed
    componentDidUpdate(prevProps, prevState) {
       // if condition is matched then do something
    }

}

【讨论】:

    猜你喜欢
    • 2017-12-13
    • 1970-01-01
    • 2023-01-30
    • 2017-12-05
    • 1970-01-01
    • 2011-07-27
    • 2015-07-16
    • 2012-01-31
    • 2011-03-24
    相关资源
    最近更新 更多