I am trying to convert my function based components to class based components. Can someone guide me how I can do that: Here is function based component:
import React, { useEffect, useState } from "react"
import ReactMapGL, { Marker, Popup } from "react-map-gl"
import RsuMarker from './RsuMarker';
import mbStyle from '../styles/mb_style.json';
function Map(props) {
const [viewport, setViewport] = useState({
latitude: 39.7392,
longitude: -104.9903,
width: 'calc(100% - 350px)',
height: '100vh',
zoom: 10
});
const [selectedRsu, setSelectedRsu] = useState(null);
const [selectedRsuCount, setSelectedRsuCount] = useState(null);
useEffect(() => {
const listener = e => {
if (e.key === "Escape")
setSelectedRsu(null);
};
window.addEventListener("keydown", listener);
return () => {
window.removeEventListener("keydown", listener);
}
}, []);
return (
<div>
<ReactMapGL
{...viewport}
mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_TOKEN}
mapStyle={mbStyle}
onViewportChange={(viewport) => {
setViewport(viewport);
}}>
{props.rsuData.map((rsu) => (
<Marker
key={rsu.id}
latitude={rsu.geometry.coordinates[1]}
longitude={rsu.geometry.coordinates[0]}>
<button
class="marker-btn"
onClick={(e) => {
e.preventDefault();
setSelectedRsu(rsu);
if (props.rsuCounts.hasOwnProperty(rsu.properties.Ipv4Address))
setSelectedRsuCount(props.rsuCounts[rsu.properties.Ipv4Address].count);
else
setSelectedRsuCount(0);
}}>
<RsuMarker onlineStatus={rsu.onlineStatus}/>
</button>
</Marker>
))}
{selectedRsu ? (
<Popup
latitude={selectedRsu.geometry.coordinates[1]}
longitude={selectedRsu.geometry.coordinates[0]}
onClose={() => {
setSelectedRsu(null);
setSelectedRsuCount(null);
}}>
<div>
<h2 class="popop-h2">{selectedRsu.properties.Ipv4Address}</h2>
<p class="popop-p">Online Status: {selectedRsu.onlineStatus}</p>
<p class="popop-p">Milepost: {selectedRsu.properties.Milepost}</p>
<p class="popop-p">
Serial Number: {selectedRsu.properties.SerialNumber ?
selectedRsu.properties.SerialNumber : 'Unknown'}
</p>
<p class="popop-p">BSM Counts: {selectedRsuCount}</p>
</div>
</Popup>
) : null}
</ReactMapGL>
</div>
);
}
export default Map;
Here is what I have done so far. It is not much , but any guidance in right direction things for example things I need to fix in code will be appreciated. Kind of very much lost at this point.
import React, { Component } from 'react';
import ReactMapGL, { Marker, Popup } from "react-map-gl"
import RsuMarker from './RsuMarker';
import mbStyle from '../styles/mb_style.json';
import {render} from 'react-dom';
class Map extends Component {
constructor(props) {
super(props)
this.state = {
viewport: {
latitude: 39.7392,
longitude: -104.9903,
width: 'calc(100% - 350px)',
height: '100vh',
zoom: 10
},
SelectedRsu : null,
SelectedRsuCount : null,
}
this.setState({'viewport': viewport});
render()
{
return (
<div>
<ReactMapGL
{...viewport}
mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_TOKEN}
mapStyle={mbStyle}
onViewportChange={(viewport) => {
setViewport(this.viewport);
}}>
{props.rsuData.map((rsu) => (
<Marker
key={rsu.id}
latitude={rsu.geometry.coordinates[1]}
longitude={rsu.geometry.coordinates[0]}>
<button
class="marker-btn"
onClick={(e) => {
e.preventDefault();
setSelectedRsu(rsu);
if (props.rsuCounts.hasOwnProperty(rsu.properties.Ipv4Address))
setSelectedRsuCount(this.props.rsuCounts[rsu.properties.Ipv4Address].count);
else
setSelectedRsuCount(0);
}}>
<RsuMarker onlineStatus={rsu.onlineStatus}/>
</button>
</Marker>
))}
{selectedRsu ? (
<Popup
latitude={selectedRsu.geometry.coordinates[1]}
longitude={selectedRsu.geometry.coordinates[0]}
onClose={() => {
setSelectedRsu(null);
setSelectedRsuCount(null);
}}>
<div>
<h2 class="popop-h2">{selectedRsu.properties.Ipv4Address}</h2>
<p class="popop-p">Online Status: {selectedRsu.onlineStatus}</p>
<p class="popop-p">Milepost: {selectedRsu.properties.Milepost}</p>
<p class="popop-p">
Serial Number: {selectedRsu.properties.SerialNumber ?
this.props.selectedRsu.properties.SerialNumber : 'Unknown'}
</p>
<p class="popop-p">BSM Counts: {selectedRsuCount}</p>
</div>
</Popup>
) : null}
</ReactMapGL>
</div>
);
}
}
}
export default Map;
Error messages I am getting:
src\components\Map.js
Line 24:36: 'viewport' is not defined no-undef
Line 25:5: 'render' is not defined no-undef
Line 30:21: 'viewport' is not defined no-undef
Line 34:19: 'setViewport' is not defined no-undef
Line 47:25: 'setSelectedRsu' is not defined no-undef
Line 49:27: 'setSelectedRsuCount' is not defined no-undef
Line 51:27: 'setSelectedRsuCount' is not defined no-undef
Line 59:20: 'selectedRsu' is not defined no-undef
Line 61:33: 'selectedRsu' is not defined no-undef
Line 62:34: 'selectedRsu' is not defined no-undef
Line 64:25: 'setSelectedRsu' is not defined no-undef
Line 65:25: 'setSelectedRsuCount' is not defined no-undef
Line 69:47: 'selectedRsu' is not defined no-undef
Line 70:60: 'selectedRsu' is not defined no-undef
Line 71:55: 'selectedRsu' is not defined no-undef
Line 73:43: 'selectedRsu' is not defined no-undef
Line 76:57: 'selectedRsuCount' is not defined no-undef
CodePudding user response:
Why are you doing set state again You already did set state inside constructor.
Remove that set state line that will work. Check the article to know more about class based components. https://medium.com/swlh/class-based-components-in-react-440eb8ed85a0
CodePudding user response:
A class component would look something like this.
import React, { Component } from "react";
import ReactMapGL, { Marker, Popup } from "react-map-gl";
class Map extends Component {
constructor(props) {
super(props);
this.state = {
viewport: {
latitude: 39.7392,
longitude: -104.9903,
width: "calc(100% - 350px)",
height: "100vh",
zoom: 10
},
selectedRsu: null,
selectedRsuCount: null
};
}
render() {
const { viewport, selectedRsu, selectedRsuCount } = this.state;
return (
<div>
<ReactMapGL
{...viewport}
mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_TOKEN}
onViewportChange={(viewport) => {
this.setState({ viewport });
}}
>
{this.props.rsuData?.map((rsu) => (
<Marker
key={rsu.id}
latitude={rsu.geometry.coordinates[1]}
longitude={rsu.geometry.coordinates[0]}
>
<button
class="marker-btn"
onClick={(e) => {
e.preventDefault();
this.setState({
selectedRsu: rsu
});
}}
></button>
</Marker>
))}
{selectedRsu ? (
<Popup
latitude={selectedRsu.geometry.coordinates[1]}
longitude={selectedRsu.geometry.coordinates[0]}
onClose={() => {
this.setState({
selectedRsu: null,
selectedRsuCount: null
});
}}
>
<div>
<h2 class="popop-h2">{selectedRsu.properties.Ipv4Address}</h2>
<p class="popop-p">Online Status: {selectedRsu.onlineStatus}</p>
<p class="popop-p">
Milepost: {selectedRsu.properties.Milepost}
</p>
<p class="popop-p">
Serial Number:{" "}
{selectedRsu.properties.SerialNumber
? selectedRsu.properties.SerialNumber
: "Unknown"}
</p>
<p class="popop-p">BSM Counts: {selectedRsuCount}</p>
</div>
</Popup>
) : null}
</ReactMapGL>
</div>
);
}
}
export default Map;
Things to note when working with React Class components.
- When accessing a prop, access via
this.props.propName
. - When accessing a state variable, access via
this.state.stateVariableName
. - When setting state, set it with an object with the new values like:
this.setState({stateVariableName: 'newValue' })
and the object will be merged with the existingstate
.