Custom component with external lib

I’m building a custom component which wraps an external library. Upon initialization, the lib is doing the rendering of its own UI components within a div which is passed as a parameter:

const libObject = new extLib(parentDiv)

So my component is just rendering a div which I want to pass to new extLib():

return( <div id={id} style={{display:"block"}}></div> )

Now my question is, when to call new extLib()? Somehow, I have to wait for the point in time when the div returned by my component really exists in the DOM tree. Otherwise, new extLib() throws an error.

I know there are techniques like “Mutation Observers” but this really clumsy and very unspecific. Is there anything else from the arsenal of React which I can reuse here?

Regards,

HI @Klaas_Klever

You need to use React Ref instead https://reactjs.org/docs/refs-and-the-dom.html

import { useRef, useEffect } from 'react'

function MyComponent(){
 const elRef = useRef(null)

 useEffect(()=>{
  const div = elRef.current
  ...
},[])  

 return (
  <div ref={elRef}/>
 )
}

Works well. Thanks you! Again something I have to learn and understand about React components.

I’m glad it works for you!

Hi @vladimir-upirov ,
I have an issue with logic handlers when using the above approach. Using your approach, I ended up with:

import { useRef, useEffect } from 'react'

export default function myComponent({ component, eventHandlers }) {
 const elRef = useRef(null)

 useEffect(()=>{
    const div = elRef.current
    const libObject = new extLib(div, component.property1)
 },[])  

 return (
  <div ref={elRef}/>
 )
}

Note, that I’m using the property component.property1 to create an instance of extLib. This works fine as long as the value of property1 is determined by a direct text entry in the property configuration in UI Builder, or when using data binding to the page data model. If I’m determining the value of property1 by a “Logic Handler”, then its value is undefined when my function declared in useEffect() is executed.
It seems that the logic handlers for properties are run “too late” to do the initialization this way. When debugging with console.log() and print- statements, I’m seeing that this is indeed happening.

Do you know any option to solve this? How to do the initialization step new extLib(div, component.property1) after the logic handler for property1 has been run?

Regards,

Hi @Klaas_Klever

Yes, logic in handlers runs async, apart from that, your dev-customer at any time can change it using “SetPropertyIn” block, or the value might depend on a data model through data-binding and so on.
Therefore your component should be ready for reflecting the current value.

the useEffect hook has an ability to register a cleanup function https://reactjs.org/docs/hooks-effect.html#example-using-hooks-1

it will run each time when the property is changed, and you will be able to remove the prev instance and register a new one.

 useEffect(()=>{
    let libObject

   if(component.property1){
    libObject = new extLib(elRef.current, component.property1)
   }

  return () => { // this is a cleanup callback
     if(libObject){
       libObject.destroy()
     }
  }
 },[component.property1]) 

But, perhaps there is a way to update the lib instance without destroying it

Regards, Vlad

Hi @vladimir-upirov
It seems that I can do simpler without using the cleanup callback. It works, if I’m registering useEffect for property1 only.

 useEffect(()=>{
    let libObject

   if(component.property1) {
    libObject = new extLib(elRef.current, component.property1)
   }
 },[component.property1])

This instantiates the lib object only if component.property1 gets a defined value.

Thanks,

yes, but pay attention it will be running each time when the property1 is changed

Sure, thanks