简体   繁体   English

有没有办法在功能组件上新渲染之前执行清理 function

[英]Is there any way to perform a cleanup function before the new render on a functional component

Description描述

I have SomeComponent which uses a some library (we'll call domLib ) that mutates the DOM directly (eg modifies and adds several elements & listeners).我有SomeComponent它使用一个库(我们将调用domLib )直接改变 DOM(例如修改和添加几个元素和侦听器)。 SomeComponent also accepts props data which domlib uses SomeComponent还接受domlib使用的道具数据

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 must also be able to see/modify HelpComponent or the children of ' example-container ' domLib还必须能够查看/修改HelpComponent或“ example-container ”的子项

  • SomeComponent accepts the props, data SomeComponent接受道具、数据
  • A child of SomeComponent named HelpComponent uses the prop data SomeComponent的一个名为HelpComponent的子组件使用道具数据
  • A library domLib uses both the data and HelpComponent to mutate the DOM (children of the ' example-container ')一个库domLib使用数据HelpComponent来改变 DOM(' example-container '的孩子)

Problem问题

When receiving new props/updating, since the cleanup function runs AFTER render, the domLib.destroy('example-container');当接收新的道具/更新时,由于清理 function在渲染后运行, domLib.destroy('example-container'); removes the children of example-container which means <HelpComponent data={data}/> will also be removed移除example-container的孩子,这意味着<HelpComponent data={data}/>也将被移除

Attempts and Issues尝试和问题

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>)

Attempt , Create everything inside the useEffect hook using ReactDom and remove everything I need to right before it.尝试,使用ReactDomuseEffect钩子中创建所有内容,并在它之前删除我需要的所有内容。

Issue , the render method in ReactDom.render(<HelpComponent data={data}/>, document.getElementById('example-container')) does not immediately apply changes to the DOM therefore when domLib cannot see HelpComponent问题ReactDom.render(<HelpComponent data={data}/>, document.getElementById('example-container'))中的渲染方法不会立即将更改应用到 DOM,因此当domLib看不到HelpComponent

Edit for extra clarity编辑以获得额外的清晰度

The library domLib is jsPlumb which I am using to create links between elements. domLib 库是jsPlumb ,我用它来创建元素之间的链接。 The elements are created based on the data prop, and the lib jsPlumb creates links between those elements.元素是基于 data 属性创建的,lib jsPlumb 在这些元素之间创建链接。

The issue is the elements created from jsPlumb are outside of the react ecosystem, so it remains between updates, therefore I need to remove them between updates问题是从 jsPlumb 创建的元素在反应生态系统之外,所以它仍然在更新之间,因此我需要在更新之间删除它们

Add [] as a second argument for useEffect so it would run once.添加[]作为useEffect的第二个参数,以便它运行一次。 If you need any props for your lib, add them to watch after changes.如果您的库需要任何道具,请将它们添加到更改后观看。 Your hook would run only then.你的钩子只会在那时运行。 For more great information, written by Dan: https://overreacted.io/a-complete-guide-to-useeffect/ or docs: https://reactjs.org/docs/hooks-reference.html#conditionally-firing-an-effect有关更多重要信息,由 Dan 编写: https://overreacted.io/a-complete-guide-to-useeffect/或文档: https://reactjs.org/docs/hooks-reference.html#conditionally-firing-效果

EDIT: to watch certain props changes, add them to the square brackets in useEffect .编辑:要观看某些道具更改,请将它们添加到useEffect中的方括号中。 An example from the docs:文档中的一个示例:

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

If you want to call destroy method just once, not depending on data changes, do this:如果您只想调用一次 destroy 方法,而不依赖于数据更改,请执行以下操作:

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

Empty function body would do nothing on the first run, but the returned function would run on destroy.空的 function 主体在第一次运行时不会执行任何操作,但返回的 function 将在销毁时运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在useEffect清理函数执行之前获取“无法对卸载的组件执行React状态更新” - Getting 'Can't perform a React state update on an unmounted component' before useEffect cleanup function executes 如何使用返回任何元素数组的渲染函数对 Vue.js 功能组件进行单元测试? - How do you unit test a Vue.js functional component with a render function that returns any array of elements? 在 React.js 的功能组件中首次渲染之前调用 api - Call api before first render in functional component in React.js 如何将内容传递到渲染 function(功能组件)中的插槽 - Vue - How to pass content to a slot in render function (functional component) - Vue 警告:无法对未安装的组件执行 React state 更新。 使用效果清理 function - Warning: Can't perform a React state update on an unmounted component. useEffect cleanup function 作为回应,在Render()之前执行API调用和重定向的最佳方法是什么? - In react, what is the best way to perform an API call and redirect before Render()? 在 react js 中渲染新组件 onClick 的方法 - Way to render a new component onClick in react js 在变量更改时渲染功能组件 - Render functional component on variable change ReactJS功能组件渲染错误 - ReactJS functional component render error 反应功能组件不呈现 - react functional component does not render
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM