Временное решение:
Лучший обходной путь, который я смог найти до сих пор - я оставлю это открытым на случай, если кто-то придумает что-то лучше. Две части:
Назначьте ключ для очистки кеша, как в приведенном ниже обновлении (используйте UUID или что-то лучше, чем Math.random. Это устранит первоначальную проблему, но создаст новую проблему, заключающуюся в том, что последующие рендеры будут вызывать ошибки при редактировании. из уже не существующей геометрии.
Исправьте эту второстепенную проблему, отслеживая режим редактирования и отключая рендеринг для компонента карты, возвращая shouldComponentUpdate false на время редактирования, примерно так:
shouldComponentUpdate(){ return !isEditingGeometry(); }
Обновление:
Поскольку я опубликовал это, я начал работать с предположением, что это проблема жизненного цикла DOM/React. Это «решает» проблему самым глупым образом:
<Polygon key={Math.random()} positions={positions}/>
Я собираюсь оставить вопрос открытым на случай, если у кого-то появится идея получше или я придумаю более надежное исправление, но сейчас у меня сложилось впечатление, что эта проблема не в моем коде, а что-то в одном или нескольких из библиотеки, но я не уверен, как это исправить, и меня немного смущает, что это не известная проблема. Наверняка кто-то где-то использует листовки в продакшене?
Вопрос:
У меня есть проект, в котором я пытаюсь использовать инструменты редактирования листовок в контексте реакции. Ниже приведен пример самой простой реализации этого, который отражает то, что я делаю. Если вы создадите новое приложение 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;