为什么多个React-Renders破坏了单张绘图编辑,我该如何解决?

时间:2018-09-08 14:29:03

标签: reactjs react-leaflet leaflet.draw

解决方法:

到目前为止,我能找到的最好的解决方法-如果有人提出更好的建议,我将保持开放。两部分:

  1. 分配一个“缓存清除”键,如下面的更新所示(使用UUID或比Math.random更好的东西。这将解决最初的问题,但会产生一个新的问题,即后续的渲染会导致错误

  2. 编辑禁用时,尝试从不再存在的几何图形上脱钩。
  3. 通过跟踪编辑模式并通过在编辑过程中返回shouldComponentUpdate false来禁用地图组件的渲染来解决此次要问题,如下所示:

    shouldComponentUpdate(){
        return !isEditingGeometry();
    }
    

更新

自从我发布此内容以来,我就开始假设这是DOM / React生命周期问题。这样可以以最愚蠢的方式“解决”该问题:

<Polygon key={Math.random()} positions={positions}/>

如果有人有更好的主意或者我想出一个更强大的解决方法,我将保留这个问题,但是现在我的印象是这个问题不在我的代码中,而是在一个代码中或更多的库,但是我不确定如何设置它,而令我困惑的是这不是一个已知问题。肯定有人在某处的生产中使用传单抽签吗?


问题:

我有一个项目,在这个项目中我试图在react上下文中使用传单绘制编辑工具。下面是此操作的最基本实现示例,它反映了我在做什么。如果您创建一个新的create-react-app并将此代码替换为App.js,则可以运行它并查看错误。

会发生什么:地图渲染,形状渲染。如果单击“编辑”按钮,则将为几何图形指定手柄,您可以对其进行调整。很好。

如果随后发生渲染(我通过使用计时器更改状态来在示例代码中对此进行伪造),则在单击“编辑”时,几何将接收到手柄,但无法调整-仅手柄会移动。取消并再次单击“编辑”(在另一个渲染之前),可以编辑形状。

这让我发疯-我遇到过几篇文章,指出在4.12版之后,传单绘制和多边形编辑存在一般性问题,但是锁定该版本似乎无济于事(我只是得到了一笔奖励大量已弃用的警告)。

这是库中的错误,还是我在未看到的反应方面做了一些愚蠢的事情?任何想法,甚至功能性的解决方法,我们深表感谢。

Relevant lines from package.json: 
   "react": "^16.2.0", 
   "react-leaflet": "^1.8.0", 
   "react-leaflet-draw": "^0.18.0", 
   "leaflet": "^1.3.0", 
   "leaflet-draw": "^0.4.9",

import React, {Component} from 'react';

import './App.css';
import {
	Map,
	Circle,
	LayersControl,
	FeatureGroup,
	Polygon,
	TileLayer
} from 'react-leaflet';
import {EditControl} from "react-leaflet-draw"

class App extends Component {

	constructor(props) {
		super(props);
		this.state={
			thing:'stuff'
		}
	}

	componentDidMount(){
		// This is a demo hack just to force a second render
		setTimeout(() => {
			this.setState({thing:'otherstuff'});
		}, 2000);
	}

	render() {
		console.log("Render...");
    
    // Building geometries like this into an array and then in return 
    // mimics what my production code is doing, but I see the same problem 
    // if I put the geometry JSX inline below 
		let positions =[[37, -109.05],[41, -109.03],[41, -102.05],[37, -102.04]];
		let tileServerURL='http://tile.stamen.com/watercolor/{z}/{x}/{y}.png';
		let editableGeometry = [];
		editableGeometry.push(<Circle key="circle" center={[37, -109.05]} radius={2000} />);
		editableGeometry.push(<Polygon key="polygon" positions={positions}/>);


		return (
			<div style={{width:'100vw',height:'100vh'}}>
			<Map ref='map' center={[37, -109.05]} zoom={13} className="ps_n3_mapComponent" style={{width:'100vw',height:'100vh'}}>
				<LayersControl position='topright'>
					<TileLayer key="tilelayer" url={tileServerURL}/>
					<FeatureGroup ref='editableFeaturegroup'>
						<EditControl/>
						{editableGeometry}
					</FeatureGroup>
				</LayersControl>
			</Map>
		</div>);
	}
}

export default App;

3 个答案:

答案 0 :(得分:0)

在使用React Leaflet时,我也遇到了同样的问题。我很沮丧,无法编写自己的传单实现作为React组件。看看:https://github.com/Chris502/PureLeafletMap

它仍然需要一些才能接受更多的配置道具,目前正在使用这些配置道具,但是我认为这是一个好的开始。

*编辑*
这不能解决react-leaflet和leaflet-draw的实际问题。这是一个地图组件,可让您加载geoJSON要素/绘制并编辑它们,而无需使用Edit Mode布尔值或shouldComponentUpdate逻辑。我将得到一个可行的例子。

答案 1 :(得分:0)

我在让反应传单画画合作方面也遇到了问题。我也很沮丧,无法在此处实施分叉:https://github.com/andrewdodd/react-leaflet-draw

我对react-leaflet-draw的主要挫败是它自动将FeatureGroup嵌入控件中,用于在编辑时存储形状,但是不能与之交互或修改。在执行React方法(即不是面向DOM的leaflet.js方法)时,这会引起各种问题,这很可能就是您遇到的问题。

在我的fork中读取代码可能会使您相信,编写自己的包装程序(或将文件从fork复制到您的项目中)更加容易。

FWIW,“示例”实际上比库本身更难以阅读和理解,因为示例必须处理存储状态等。

答案 2 :(得分:0)

如果使用react功能组件,则多边形坐标来自props。您应该使用useEffect和useState,并且当props更改整个组件的重新渲染时。

const EditPolygon = ({ coordinates }: OwnProps) => {
  const [polygonData, setPolygonData] = useState()

  useEffect(() => {
    setPolygonData(coordinates)
  }, [coordinates]) 

return (
<FeatureGroup>
  <EditControl />
<Polygon positions={coordinates} key={some.id}>
</FeatureGroup>
)