1

按照高级组件工厂的官方参考来更新控制组件的道具

核心 API 导出其他可以以类似方式使用的高级组件工厂。

我模仿了这个例子 - 但我收到以下语法错误:

import L from "leaflet";
import "leaflet-routing-machine";
import { createControlComponent } from "@react-leaflet/core";
import 'leaflet-routing-machine/dist/leaflet-routing-machine.css'

function setWaypoints(props)
{
    return { 
        waypoints: [
        L.latLng(props.startLat, props.startLng),
        L.latLng(props.endLat, props.endLng)
        ],
        lineOptions: {
            styles: [{ color: "#0500EE", weight: 4 }]
        },
        show: false,
        addWaypoints: false,
        routeWhileDragging: true,
        draggableWaypoints: true,
        fitSelectedRoutes: true,
        showAlternatives: false,
        createMarker: function() { return null; },

    }
}


function createRoutingMachine(props, context) 
{
    const instance =  new L.Routing.control(setWaypoints(props))
    return 
    { 
        instance, context: { ...context, overlayContainer: instance }    
    }
}


function updateRoutingMachine(instance, props, prevProps)
{
    if (props.endLat !== prevProps.endLat || props.endLng !== prevProps.endLng) 
    {
        instance.setWaypoints(props)
    }
}

const RoutingMachine = createControlComponent(createRoutingMachine, updateRoutingMachine)
export default RoutingMachine;

缺少分号。(35:25)

33 | 返回 34 | {

35 | 实例,上下文:{ ...上下文,overlayContainer:实例}
| ^ 36 | }

如果我将其更改为:


function createRoutingMachine(props) 
{
    const instance =  new L.Routing.control(setWaypoints(props))
    return instance
}

编译器很高兴,但组件永远不会更新。

我知道我错误地创建了控制组件,但我找不到正确实现的信息。

相关:
如何在 React-Leaflet 3 中使用 Leaflet Routing Machine?
如何在 react-leaflet v3 中扩展 TileLayer 组件?

4

1 回答 1

2

您会注意到,在文档中,createcontrolcomponent仅列出了一个参数,即创建实例的函数。您期望它的行为类似于createlayercomponent,它需要两个参数。在 createlayercomponent 中,第二个参数是一个函数,用于在 props 更改时更新图层组件。但是,createcontrolcomponent不提供此类功能。react-leaflet 假设,就像香草传单一样,一旦你的控件被添加到地图中,你就不需要直接改变它。

就传单路由机器而言,这有点令人困惑,因为您不需要更改控件的实例,而是需要在其上调用影响地图呈现的方法。

IMO,最好的方法是使用状态变量来跟踪您的航点是否已更改,并使用 ref 访问路由机器的底层传单实例,并调用setWayPoints它:

// RoutineMachine.jsx

const createRoutineMachineLayer = (props) => {
  const { waypoints } = props;
  const instance = L.Routing.control({
    waypoints,
    ...otherOptions
  });

  return instance;
};

// Takes only 1 argument:
const RoutingMachine = createControlComponent(createRoutineMachineLayer);
// Map.jsx

const Map = (props) => {
  // create a ref
  const rMachine = useRef();
  // create some state variable, any state variable, to track changes
  const [points, setPoints] = useState(true);
  const pointsToUse = points ? points1 : points2;

  // useEffect which responds to changes in waypoints state variable
  useEffect(() => {
    if (rMachine.current) {
      rMachine.current.setWaypoints(pointsToUse);
    }
  }, [pointsToUse, rMachine]);

  return (
    <MapContainer {...props}>
      <RoutineMachine ref={rMachine} waypoints={pointsToUse} />
      <button onClick={() => setPoints(!points)}>
        Toggle Points State and Props
      </button>
    </MapContainer>
  );
};

工作代码沙盒

<RoutineMachine>奖励:在您的组件(或任何反应组件)上强制重新渲染的一种廉价且简单的方法是为其分配一个key道具,并在您想要重新渲染它时更改该关键道具。这可能是一个 uuid,甚至是通过 JSON.stringify 运行的一组独特的航路点。只是一个想法。

于 2021-05-24T14:30:41.343 回答