Tengo una clase que hereda React.Component como tal:
import { Component } from "react" import {Map} from "ol" // the goal is to render a map with openlayers import './MapCanvas.css' class MapCanvas extends Component { constructor(props) { super(props) this.state = {} } componentDidMount() { console.log('hello') // called twice const canvas = new Map(/* map options, irrelevant here */) this.setState({canvas}) } componentWillUnMount () { console.log('goodbye') // never called if (this.state && this.state.canvas) { this.state.canvas.setTarget(undefined) // should remove the map } } render() { return ( <div id="map" className="map"></div> ) } } export default MapCanvasMi aplicación se ve así
import MapCanvas from './components/MapCanvas' import './App.css' function App() { return ( <MapCanvas/> ) } export default Appy el índice es
import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import App from './views/App'; const root = createRoot(document.getElementById('app')) root.render( <StrictMode> <App/> </StrictMode> ) Si elimino StrictMode , todo se ve bien. Sin embargo, si lo dejo, el método componentDidMount de MapCanvas se llama dos veces y termino teniendo 2 mapas en la página. componentWillUnmount nunca se llama en el proceso.
Leí aquí y allá que React StrictMode llama a algunas funciones varias veces en el modo de desarrollo.
Por lo que entendí, es para ayudarnos a codificar de una manera más limpia, pero no puedo entender lo que se supone que debo hacer.
Mi pregunta es, ¿dónde se supone que debo configurar ol.Map para que respete las mejores prácticas y se llame solo una vez, O se "destruya" correctamente en la actualización?
Justo al publicar la pregunta, me di cuenta de que tenía un error tipográfico en componentWillUnmount (M en lugar de m). Lo corregí, ahora veo "adiós" en la consola, pero todavía tengo 2 mapas. Si esta pregunta es más sobre openlayer que sobre reaccionar, infórmelo en los comentarios y lo actualizaré o eliminaré.
El uso de atributos de clase en lugar del estado React para almacenar el lienzo da el resultado esperado. ¿Se considera esto una buena práctica o hay una mejor manera?
Aquí hay una solución que funcionó para mí: usar un atributo de clase en lugar de React State
import { Component, createRef } from "react" import { Map } from "ol" class MapCanvas extends Component { constructor(props) { super(props) this.canvas = new Map(/* options */) this.ref = createRef() } componentDidMount() { this.canvas.setTarget(this.ref.current) } componentWillUnmount () { this.canvas.setTarget(undefined) } render() { return ( <div ref={this.ref} className="map"></div> ) } } export default MapCanvasPuede que no sea una buena práctica de reacción, pero resuelve el problema por ahora.
Si tiene una solución mejor, puede publicar una respuesta. Consideraré aceptarla en su lugar.