Home > Enterprise >  How to convert function to class based components in react?
How to convert function to class based components in react?

Time:10-23

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 existing state.
  • Related