Inheriting component that uses useImperativeHandle exposed api

29 Views Asked by At

Can't get throght problem of wrapping a component that exposes ref with some api. I need to add some functionality to it and export the same api to its users. I don't need to add new methods to this api. In other words the problem sounds like: reexport and reuse ref, created by useImperativeHandle in another component.

The approach I'm trying to take is to use the ref from original Map and reexport it upwards to the user consumer code so that user could also use it to set the center:

type MapProps = {};
type MapRefType = {
  setCenter: (x: number, y: number) => void;
}

function MapWithRef({ }: MapProps, ref: Ref<MapRefType>) {
  useImperativeHandle(ref, () => ({
    setCenter: (x, y) => doSetCenter(x, y)
  }));

  return <MapRenderer 
      // some props
  />
}

export const Map = forwardRef(MapWithRef);

-------------------

function MapWithSearchWithRef({ }: MapProps, ref: Ref<MapRefType>) {
  const inheritedRef = useRef<MapRefType>(null);

  useEffect(() => {
        if (ref != null && ref != undefined) {
            if (typeof ref === 'function') {
                ref(inheritedRef.current);
            } else {
                ref.current = inheritedRef.current; // <-- ERROR: ref.current is readonly
            }
        }
  }, [inheritedRef.current, ref]);

  useEffect(() => {
    inheritedRef.setCenter(10, 10);
  }, [someCondition]);

  return <Map
    ref={inheritedRef}
  />
}

export const MapWithSearch = forwardRef(MapWithSearchWithRef);

---------------------

function Page() {
  const ref = useRef<MapRefType>(null);

  useEffect(() => {
    ref.setCenter(0, 0);
  }, [someCondition]);

  return <MapWithSearch
    ref={ref}
  />
}

I suppose the limitation of a readonlyness of ref passed by forwardRef in MapWithSearchWithRef is not like that, but has some serious reasons.

How can it be solved?

Upd: I've managed to replace Ref type in component parameters to ForwardedRef and the error gone. But the question is: if this approach normal? It looks not good.

0

There are 0 best solutions below