【问题标题】:Is there any way to perform a cleanup function before the new render on a functional component有没有办法在功能组件上新渲染之前执行清理功能
【发布时间】:2019-09-25 15:06:11
【问题描述】:

说明

我有 SomeComponent,它使用了一些库(我们将调用 domLib)来改变 DOM直接(例如修改并添加几个元素和侦听器)。 SomeComponent 也接受 domlib 使用的 props data

const SomeComponent = ({ data }) => {
    useEffect(() => {
        domLib.init(data, 'example-container');
        return () => { //cleanup function
            domLib.destroy('example-container'); //removes everything from example-container, listeners etc from example-container
        }
    },[data])
    return (<div id='example-container'>
        <HelpComponent data={data}/>
    </div>)
}

domLib 还必须能够查看/修改 HelpComponent 或 'example 的子级-容器'

  • SomeComponent 接受道具,data
  • 一个名为 HelpComponent 的 SomeComponent 子组件使用道具数据
  • 库 domLib 使用 data 和 HelpComponent 改变 DOM('example-container' 的子级)

问题

当接收到新的 props/更新时,由于 cleanup 函数 在渲染之后运行,domLib.destroy('example-container'); 会移除 example-container 的子元素,这意味着 &lt;HelpComponent data={data}/&gt; 也会被删除

尝试和问题

useEffect(() => {
    domLib.destroy('example-container');
    ReactDom.unmountComponentAtNode(document.getElementById('example-container'))
    ReactDom.render(<HelpComponent data={data}/>, document.getElementById('example-container'))
    domLib.init(data, 'example-container');
})
return (<div id='example-container'>
    {/* removed */}
</div>)

尝试,使用 ReactDom 在 useEffect 钩子中创建所有内容,然后删除我需要的所有内容。

问题,ReactDom.render(&lt;HelpComponent data={data}/&gt;, document.getElementById('example-container')) 中的渲染方法不会立即将更改应用到 DOM,因此当 domLib 看不到 帮助组件

进行编辑以提高清晰度

库 domLib 是 jsPlumb,我用它来创建元素之间的链接。元素是基于 data 属性创建的,而 lib jsPlumb 在这些元素之间创建链接。

问题是从 jsPlumb 创建的元素在 react 生态系统之外,所以它在更新之间保留,因此我需要在更新之间删除它们

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    添加[] 作为useEffect 的第二个参数,这样它就会运行一次。如果您的库需要任何道具,请将它们添加到更改后观看。你的钩子只会在那时运行。更多精彩信息,作者:https://overreacted.io/a-complete-guide-to-useeffect/ 或文档:https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect

    编辑:要查看某些道具更改,请将它们添加到 useEffect 的方括号中。文档中的一个示例:

    useEffect(
      () => {
        const subscription = props.source.subscribe();
        return () => {
          subscription.unsubscribe();
        };
      },
      [props.source],
    );
    

    如果你只想调用一次destroy方法,不依赖于数据变化,这样做:

    useEffect(
      () => {
        return () => {
          subscription.unsubscribe();
        };
      },
      [],
    );
    

    空函数体在第一次运行时不会执行任何操作,但返回的函数会在销毁时运行。

    【讨论】:

    • 我忘记在我的示例中添加 [data] 作为第二个参数,但是这并没有任何帮助,首先我需要它在道具更改时再次运行,我也是不知道“如果您的库需要任何道具,请在更改后添加它们以观看”是什么意思
    • @steff_bdh 我添加了更新。我建议检查文档,那里只有几个关于问题主题的段落。会比我解释得更好。
    • 谢谢,但是我看不出限制我的更新如何有助于清理在 React 生态系统之外创建的元素,在这种情况下,我是否有一系列依赖关系并不重要,因为有在这个组件中没有更新状态
    • @steff_bdh 也许我当时不理解你。您是否需要在每次更新后清理&lt;div id='example-container'&gt;,但又想保留&lt;HelpComponent data={data}/&gt;?这个库在哪里使用'HelpComponent 来改变 DOM'(你不会在任何地方传递它)?
    • 它使用容器'example-container'的孩子,为了清晰起见,我将添加一个编辑,就期望的结果而言,1>'example-container'中的老孩子和人工制品是已删除 2> 'example-container' 的新子级是基于新道具创建的 3> domLib 创建新的人工制品并操作 'example-container' 的子级 正在使用的库是 github.com/jsplumb/jsplumb
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2023-02-17
    • 1970-01-01
    相关资源
    最近更新 更多