unmountComponentAtNode这个方法,并不陌生。

官方给出的解释是:

从 DOM 中卸载组件,会将其事件处理器(event handlers)和 state 一并清除。如果指定容器上没有对应已挂载的组件,这个函数什么也不会做。如果组件被移除将会返回 true,如果没有组件可被移除将会返回 false。

虽然在 React18 中,它已被 root.unmount() 取代。 但这不重要,项目目前的版本我也升不上去(历史原因)。

没想到,这两天还在这里栽了跟头,头大。

为什么这么说呢?看看下面的例子就明白了。

正常来说,unmountComponentAtNode只会对ReactDOM.render挂载在顶层的元素进行卸载。

效果看图:
​​在这里插入图片描述
root下面有一个div,点击卸载组件按钮之后,root下面的div不见了,说明卸载成功了。

具体代码如下:

// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

// App.js 
import React from 'react';
import ReactDOM from 'react-dom';
import { Button } from 'antd';

const App = () => {
  // 新增Dom
  const addDom = () => {
    const div = document.createElement('div');
    div.innerHTML = '不可卸载组件'
    document.getElementById('root').appendChild(div);
  }
  // 销毁组件
  const destory = () => {
    ReactDOM.unmountComponentAtNode(document.getElementById('root'));
  }
  return (
    <div>
      可卸载组件
      <Button type="primary" style={{ margin: '0 8px'}} onClick={destory}>卸载组件</Button>
      <Button type="primary" onClick={addDom}>新增DOM</Button>
    </div>
  )
}

export default App;

那如果我新增一个dom节点,并且该节点并不是直接放在ReactDOM.render里渲染的,而是通过appendChild插入到root下的。这个节点在我卸载root的时候,会被卸载掉吗?

实际操作如下:
在这里插入图片描述
很明显,卸载不成功。这也是我踩坑的地方,如果想要插入的元素也被卸载掉,可以插入到App.js的节点中,不要直接插入到根节点。

总之,unmountComponentAtNode只对ReactDOM.render挂载在顶层的组件才生效,其余无关render方法永远返回的都是false

最后,附上React18的版本(效果同上):

// index.js
import { createRoot } from 'react-dom/client';
import App from './App';

const container = document.getElementById('root');
const root = createRoot(container);
root.render(<App root={root} />);

// App.js
import React from 'react';
import { Button } from 'antd';

 const App = (props) => {
  const { root } = props;
  // 新增Dom
  const addDom = () => {
    const div = document.createElement('div');
    div.innerHTML = '不可卸载组件'
    document.getElementById('root').appendChild(div);
  }
  // 销毁组件
  const destory = () => {
    root.unmount();
  }
  return (
    <div>
      可卸载组件
      <Button type="primary" style={{ margin: '0 8px'}} onClick={destory}>卸载组件</Button>
      <Button type="primary" onClick={addDom}>新增DOM</Button>
    </div>
  )
}

export default App;
Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐