Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

useRef current getting its value only on second update

I have the following components:

const ParentComponent: React.FC = () => {
    const networkRef: any = useRef();

    // Somewhere in the code, I call this
    networkRef.current.filter(["id0, id1, id2"]);

    return (
    ...
        <VisNetwork 
            ref={networkRef}
        />
    ...
    )
}
export default ParentComponent;

interface Props {
    ref: any;
}
const VisNetwork: React.FC<Props> = forwardRef((props: Props, ref) => {
    useImperativeHandle(ref, () => ({
        filter(items: any) {
            setFilterNodes(items);
            nView.refresh();
        }
    }));

    const [filterNodes, setFilterNodes] = useState<any[]>([]);
    const filterNodesRef = useRef(filterNodes);
    useEffect(() => {
        filterNodesRef.current = filterNodes;
    }, [filterNodes]);

    ...
    // Some code to create the network (concentrate on the nodesView filter method)
    const [nView, setNView] = useState<DataView>();
    const nodesView = new DataView(nodes, {
        filter: (n: any) => {
            if (filterNodesRef.current.includes(n.id)) {
                return true;
            }
            return false;
        }
    })
    setNView(nodesView);
    const network = new vis.Network(container, {nodes: nodesView, edges: edgesView}, options);
});
export default VisNetwork;

WHen I call network.current.filter([...]), it will set the filterNodes state. Also, it should set the filterNodesRef inside the useEffect.

However, the filterNodesRef.current remains to be empty array.

But when I call network.current.filter([...]) the second time, only then the filterNodesRef.current got the value and the DataView was able to filter.

Why is it like this? I thought the useRef.current will always contain the latest value.

like image 602
iPhoneJavaDev Avatar asked Jun 05 '20 11:06

iPhoneJavaDev


People also ask

Does updating useRef Rerender?

[2:52] In summary, useRef can be used to store data values just like useState, but the difference is that when that value changes, it doesn't cause a re-render.

Does useRef notify when its content changes?

useRef doesn't notify us when its content changes. Mutating the . current property doesn't cause a re-render. If we want to run some code when React attaches or detaches a ref to a DOM node, a callback ref is better suited.

Why useRef current is null?

The "Object is possibly null" error is caused because the useRef() hook can be passed an initial value as an argument and we're passing it null as an initial value. The hook returns a mutable ref object whose . current property is initialized to the passed argument.


1 Answers

I finally solved this by calling the refresh() method inside the useEffect instead of the filter() method:

useEffect(() => {
    filterNodesRef.current = filterNodes;
    nView.refresh();
}, [filterNodes]);
like image 153
iPhoneJavaDev Avatar answered Oct 26 '22 23:10

iPhoneJavaDev