【问题标题】:How to convert function to class based components in react?如何在反应中将函数转换为基于类的组件?
【发布时间】:2021-12-09 13:20:51
【问题描述】:

我正在尝试将基于函数的组件转换为基于类的组件。有人可以指导我如何做到这一点: 这是基于函数的组件:

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;

这是我到目前为止所做的。这并不多,但任何正确方向的指导,例如我需要在代码中修复的事情,都将不胜感激。在这一点上有点迷失了。

     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;

我收到的错误消息:

     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

【问题讨论】:

  • 什么是viewport ?它应该是组件道具吗?
  • 是的,基于函数的函数 Map(props) { const [viewport, setViewport] = useState({ latitude: 39.7392, longitude: -104.9903, width: 'calc(100% - 350px)',高度:'100vh',缩放:10 });
  • 啊,我明白了。它是一个状态变量,而不是一个道具。

标签: reactjs react-native react-class-based-component


【解决方案1】:

类组件看起来像这样。

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;

使用 React Class 组件时的注意事项。

  • 访问道具时,通过this.props.propName访问。
  • 访问状态变量时,通过this.state.stateVariableName访问。
  • 设置状态时,使用具有新值的对象进行设置,例如:this.setState({stateVariableName: 'newValue' }),该对象将与现有的state 合并。

【讨论】:

    【解决方案2】:

    别忘了你也需要转换这部分代码:

    useEffect(() => {
      const listener = e => {
        if (e.key === "Escape")
          setSelectedRsu(null);
      };
      window.addEventListener("keydown", listener);
    
      return () => {
        window.removeEventListener("keydown", listener);
      }
     }, []);
    

    看起来您只是在组件安装和卸载时使用效果,这是一个简单的修复。只需将安装代码移至componentWillMount,将卸载代码移至componentWillUmount

    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
        };
      }
      //in order to be accessible to componentWillUnMount your listener has to be global
      listener = e => {
          if (e.key === "Escape")
          setState({selectedRsu:null});
         };
      componentDidMount(){
        window.addEventListener("keydown", this.listener);
      }
      componentWillUnmount(){
         window.removeEventListener("keydown", this.listener);
      }
    
      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;
    

    【讨论】:

      【解决方案3】:

      为什么又要设置状态 您已经在构造函数中设置了状态。

      删除将起作用的设置状态行。 查看文章以了解有关基于类的组件的更多信息。 https://medium.com/swlh/class-based-components-in-react-440eb8ed85a0

      【讨论】:

        猜你喜欢
        • 2020-07-31
        • 2022-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多