useImperativeHandle hook
everything you need to know about useImperativeHandle
The hook name itself describes what it does.
React is declarative UI library.
Meaning we don’t have to worry about the steps of doing certain things like manually adding click listeners. We simply declare onClick and React Manages all the stuff under the hood.
And the counter part of declarative is imperative. Where we define all steps manually. Like attaching event listeners manually.
What does useImperativeHandle do?
useImperative gives us a way to update the DOM and it’s content without the use of state
variables. As there is no involvement of state
React
won’t re-render
the component, it’s the developers
responsibility
to update the UI in imperative
manner.
UseCase:
When we have thousands of HTML blocks in the UI, and we have to show tooltip based on the clicked element, Now the easy way to do this is to use state variables to store the information about the clicked element, the downside of this is that component will be re-rendered.
We can manage this scenario by using useImperativeHandle
Let’s consider this example:
We have 100 blocks with number, and on click of each block we have to show the clicked number in a card.
Here, we have done it using state
way, on click of any block, we are updating the state variable which is keeping track of selected block.
And once state is updated, react re-renders the UI with updated value.
Problem:
The green
pulse shows the re-rendering done by react. As it is visible that on each selection whole UI is updated.
This can be a problem when the number of elements are larger.
We can solve this issue using useImperativeHandle. By updating the UI in imperative way, (Manual Way) instead of using state
to update the UI.
How does useImperativeHandle works?
useImperativeHandle is a hook which takes 2 arguments
ref
passed byforwardRef
- A function which returns an object, containing all the methods which we want to expose to parent component.
useImperativeHandle(ref, ()=> ({hide:function() {}}))
Usage in Parent Component:
const childRef = useRef();function handleClick() {childRef.current.hide(); // will call the hide method defined in userImperativeHandle}return <Child ref={childRef} />
Solving the problem using useImperativHandle
Demo:
Extending the usage:
Here we have only updated a string, but generally we have a component to update. We can use ReactDOM.render
method to update the content manually in case we have additional component used.
useImperativeHandle(ref, ()=> ({ updateUI() { // Step 1: Empty the current data
insideRef.current.innderHTML = ''; // Step 2: Create a dummy element
const temp = document.createElement('div'); // Step 3: Render the content inside dummy Element
ReactDom.render(<TooltipInfo data={data} />,temp); // Step 4: Add the Content inside our Visible Component
insideRef?.current?.appendChild(temp.childNodes[0]); // Step 5: Remove the dummy Element
temp.remove(); }}))
Caveats of useImperativeHandle:
When we pass ref
inside useImperativeHandle, DOM reference of ref
gets overridden by the returned object and none of the DOM methods will work on ref
. Due to this assigning the same ref
to any DOM element won’t work.
We have to create a separate ref
in component and use it instead of the forwarded
ref.
Thanks for Reading.