Reputation: 6166
There is a functional component implemented with getElementById and it needs to be updated to use useRef hook.
Original code:
import React, { useState, useEffect, useRef } from 'react';
import { createPortal } from 'react-dom';
const MyComponent: React.FunctionComponent<MyComponentProps> = ({
myDefaultElement = 'default-element',
}) => {
const [elementOutlet, setElementOutlet] = useState<HTMLOListElement>();
useEffect(() => {
const refElement = document.getElementById(myDefaultElement) as HTMLOListElement;
if (refElement) {
setElementOutlet(refElement);
}
}, [myDefaultElement]);
return createPortal(
<li>
// something
</li>,
elementOutlet
);
};
the above code works fine, the only change that I made was the first line inside useEffect.
From:
const refElement = document.getElementById(myDefaultElement) as HTMLOListElement;
To:
const refElement = useRef(myDefaultElement) as HTMLOListElement;
When hover the new line it says:
React Hook "useRef" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function
Is there a way to make ref work fine inside useEffect?
Upvotes: 3
Views: 12510
Reputation: 21317
You can't call useRef
inside an effect, check the rule of hooks. Try something like this
const Component = () =>{
const node = useRef(null)
useEffect(() =>{
// current will never be null here, since this effect will
// only run after the first mount and therefore after refs
// appending
setElementOutlet(node.current)
},[])
return <div ref={node} />
}
Refs already have an stable signature ensured by react's life cycle, so you don't have to declare it as a dependency inside your effect.
Judging by your example you're only receiving an id
as props not the node itself. You have two options:
getElementById
(there is nothing wrong with that) and then append the mounted node inside a refconst Component = ({ id }) =>{
const node = useRef(document.getElementById(id))
useEffect(() =>{
const el = document.getElementById(id)
if(el) node.current = el
},[id])
}
const ParentComponent = () =>{
const node = useRef(null)
return(
<>
<Component childRef={node} />
<div ref={node} />
</>
)
}
const Component = ({ childRef }) =>{
...
}
Greetings fellow olister.
Upvotes: 3