如何在 React 中将函数转换为基于 class 的组件?
How to convert function to class based components in react?
我正在尝试将基于函数的组件转换为基于 class 的组件。有人可以指导我如何做到这一点:
这是基于函数的组件:
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
class 组件看起来像这样。
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
. 合并
你为什么又要设置状态
您已经在构造函数中设置了状态。
删除有效的设置状态行。
查看文章以了解有关基于 class 的组件的更多信息。
https://medium.com/swlh/class-based-components-in-react-440eb8ed85a0
别忘了您还需要转换这部分代码:
useEffect(() => {
const listener = e => {
if (e.key === "Escape")
setSelectedRsu(null);
};
window.addEventListener("keydown", listener);
return () => {
window.removeEventListener("keydown", listener);
}
}, []);
看起来您只是在组件安装和卸载时使用效果,这是一个简单的解决方法。只需将 onmount 代码移动到 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;
我正在尝试将基于函数的组件转换为基于 class 的组件。有人可以指导我如何做到这一点: 这是基于函数的组件:
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
class 组件看起来像这样。
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
. 合并
你为什么又要设置状态 您已经在构造函数中设置了状态。
删除有效的设置状态行。 查看文章以了解有关基于 class 的组件的更多信息。 https://medium.com/swlh/class-based-components-in-react-440eb8ed85a0
别忘了您还需要转换这部分代码:
useEffect(() => {
const listener = e => {
if (e.key === "Escape")
setSelectedRsu(null);
};
window.addEventListener("keydown", listener);
return () => {
window.removeEventListener("keydown", listener);
}
}, []);
看起来您只是在组件安装和卸载时使用效果,这是一个简单的解决方法。只需将 onmount 代码移动到 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;