如何在反应中将函数转换为基于类的组件?
Posted
技术标签:
【中文标题】如何在反应中将函数转换为基于类的组件?【英文标题】: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 );
啊,我明白了。它是一个状态变量,而不是一个道具。
【参考方案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
【讨论】:
以上是关于如何在反应中将函数转换为基于类的组件?的主要内容,如果未能解决你的问题,请参考以下文章