在 react-leaflet 3 中使用 createControlComponent 时更新道具
updating props when using createControlComponent in react-leaflet 3
按照 Higher Level Component Factory 的官方参考更新控件组件的道具
The core APIs export other high-level component factories that can be
used in a similar way.
我模仿了这个例子 - 但我得到了以下语法错误:
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;
Missing semicolon. (35:25)
33 | return 34 | {
35 | instance, context: { ...context, overlayContainer: instance }
| ^ 36 | }
如果我将其更改为:
function createRoutingMachine(props)
{
const instance = new L.Routing.control(setWaypoints(props))
return instance
}
编译器很高兴,但组件永远不会更新。
我知道我创建的控制组件不正确,但我找不到正确实现的信息。
相关:
How to extend TileLayer component in react-leaflet v3?
您会注意到在文档中,createcontrolcomponent
lists only one argument, which is a function to create the instance. You are expecting it to behave like createlayercomponent
有两个参数。在 createlayercomponent 中,第二个参数是一个函数,用于在 props 发生变化时更新图层组件。但是,createcontrolcomponent
不提供此类功能。 react-leaflet 假设,就像 vanilla leaflet,一旦你的控件被添加到地图,你就不需要直接改变它。
这在 leaflet-routing-machine 方面有点混乱,因为您不需要更改控件的实例,而是需要在其上调用一个影响地图显示的方法。
IMO,最好的方法是使用状态变量来跟踪您的 waypoints 是否已更改,并使用 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>
);
};
Working Codesandbox
奖励:在 <RoutineMachine>
组件(或任何反应组件)上强制重新渲染的一种廉价且简单的方法是为其分配一个 key
道具,并在需要时更改该关键道具重新渲染它。这可能是一个 uuid,甚至是 waypoints 运行 到 JSON.stringify 的唯一集合。只是一个想法。
按照 Higher Level Component Factory 的官方参考更新控件组件的道具
The core APIs export other high-level component factories that can be used in a similar way.
我模仿了这个例子 - 但我得到了以下语法错误:
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;
Missing semicolon. (35:25)
33 | return 34 | {
35 | instance, context: { ...context, overlayContainer: instance }
| ^ 36 | }
如果我将其更改为:
function createRoutingMachine(props)
{
const instance = new L.Routing.control(setWaypoints(props))
return instance
}
编译器很高兴,但组件永远不会更新。
我知道我创建的控制组件不正确,但我找不到正确实现的信息。
相关:
How to extend TileLayer component in react-leaflet v3?
您会注意到在文档中,createcontrolcomponent
lists only one argument, which is a function to create the instance. You are expecting it to behave like createlayercomponent
有两个参数。在 createlayercomponent 中,第二个参数是一个函数,用于在 props 发生变化时更新图层组件。但是,createcontrolcomponent
不提供此类功能。 react-leaflet 假设,就像 vanilla leaflet,一旦你的控件被添加到地图,你就不需要直接改变它。
这在 leaflet-routing-machine 方面有点混乱,因为您不需要更改控件的实例,而是需要在其上调用一个影响地图显示的方法。
IMO,最好的方法是使用状态变量来跟踪您的 waypoints 是否已更改,并使用 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>
);
};
Working Codesandbox
奖励:在 <RoutineMachine>
组件(或任何反应组件)上强制重新渲染的一种廉价且简单的方法是为其分配一个 key
道具,并在需要时更改该关键道具重新渲染它。这可能是一个 uuid,甚至是 waypoints 运行 到 JSON.stringify 的唯一集合。只是一个想法。