简体   繁体   中英

React forwardRef and callback ref, ref becomes undefined

This is not a Mapbox related issue , and you don't need any map or related stuff knowledge to help. My issue is related to React refs.

I'm using react-map-gl (Mapbox for React) with @mapbox/mapbox-gl-draw that allow user to draw geometries on the map. This app has 2 components: DrawControl that exposes draw features and AllPastures that renders the map and manage create/update/delete geometries drawed.

When user draws a polygon it fires the DrawControl method onCreate that executes onCreateOrUpdate . I'm passing the Draw by forwardRef from DrawControl to AllPastures .

This is a DrawControl component:

export const DrawControl = React.forwardRef<MapboxDraw, DrawControlProps>(
  (props: DrawControlProps, ref) => {
    const drawRef: MapboxDraw = useControl<MapboxDraw>(
      () => new MapboxDraw(props),
      ({ map }) => {
        map.on('draw.create', props.onCreate);
        map.on('draw.update', props.onUpdate);
        map.on('draw.delete', props.onDelete);
        map.on('draw.modechange', props.onModeChange);
      },
      ({ map }) => {
        map.off('draw.create', props.onCreate);
        map.off('draw.update', props.onUpdate);
        map.off('draw.delete', props.onDelete);
        map.off('draw.modechange', props.onModeChange);
      },
      {
        position: props.position,
      }
    );

    // exposing drawRef outside the component by Ref
    React.useImperativeHandle(ref, () => drawRef, [drawRef]);

    return null;
  }

and this is part of AllPastures component:

export const AllPastures = () => {
  ...
  const [drawRef, setDrawRef] = React.useState<MapboxDraw>();

  // here I’m using callback ref to react to drawRef changes
  const onDrawRef = React.useCallback((ref: MapboxDraw | null) => {
    if (ref) {
      setDrawRef(ref);
    }
  }, []);

  React.useEffect(() => {
    // it's ok here, drawRef is not undefined
    console.log('useEffect drawRef when app is loading', drawRef);
  }, [map, drawRef]);

  const onCreateOrUpdate = (e: { features: Feature[] }) => {
    // Why drawRef is undefined here????????????????????
    console.log('drawRef under onCreateOrUpdate method', drawRef);
  };

  ...

  return (
      <DrawControl
        ref={onDrawRef}
        position="top-right"
        displayControlsDefault={false}
        controls={{
          polygon: true,
          trash: true,
        }}
        defaultMode="simple_select"
        onCreate={onCreateOrUpdate}
        onUpdate={onCreateOrUpdate}
      />
  );
};

My issue is, discover why when the the method onCreateOrUpdate the drawRef is undefined?


Here is a related sandbox simulating the issue: https://stackblitz.com/edit/vitejs-vite-bvutvb?file=src%2FAllPastures.tsx

Just draw any polygon on the map and check the console.log drawRef under onCreateOrUpdate method is undefined.

Please, after make changes in the code, do a F5 to complete refresh the page and test it again.

const onCreateOrUpdate = React.useCallback((e: { features: Feature[] }) => {
  // Here drawRef would not be undefined
  console.log('drawRef under onCreateOrUpdate method', drawRef);
}, [drawRef]);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM