primereact icon indicating copy to clipboard operation
primereact copied to clipboard

ForwardedRef-Components: ref cannot be accessed on useLayoutEffect lifecycle

Open nico-richter opened this issue 2 months ago • 0 comments

Describe the bug

A given ref to component can not be accessed in useLayoutEffect. The problem exists in Button and InputText, I think other components may also be affected, maybe only those which do not use useImperativeHandle.

function MyButton(){
  const ref = useRef(null);
  useLayoutEffect(() => ref.current.focus());
  return <Button ref={ref}>Click</Button>
}

Error: ref.focus is null

Here are some parts from sourcecode of Button:

export const Button = React.forwardRef((inProps, ref) => {
        const elementRef = React.useRef(ref);

        React.useEffect(() => {
            ObjectUtils.combinedRefs(elementRef, ref);
        }, [elementRef, ref]);

        const rootProps = mergeProps(
            {
                ref: elementRef,
               (...)
            },
            (...)
        );

        return (
            <>
                <button {...rootProps}>
                    (...)
                </button>
            </>
        );
}

useEffect will synchronize both ref. Therefore useLayoutEffect which runs earlier can not access the forwardedRef.

I do not understand why ref should be initValue for elementRef. const elementRef = React.useRef(ref);

Possible solution with custom hook:

function useForwardedRef(forwardedRef){
  const ref= React.useRef();
  if(forwardedRef) return forwardedRef;
  return ref;
}

export const Button = React.forwardRef((inProps, ref) => {
        const elementRef = useForwardedRef(ref);
        return (
            <>
                <input ref={elementRef} {...rootProps} />
                (...)
            </>
}

Maybe Utils.combinedRef will be obsolete.

Reproducer

No response

System Information

react 18.2
primereact 10.5.1

Steps to reproduce the behavior

No response

Expected behavior

No response

nico-richter avatar Nov 13 '25 14:11 nico-richter