React 组件中的删除按钮无法从页面获取 useState
2022-05-08
454
我正在制作一个 Google Map API 应用。但是我在从组件调用 setMarker(useState) 时遇到了问题。
它说,未捕获 TypeError:无法读取未定义的属性(读取“过滤器”)。
我想制作一个表格来显示我的搜索位置结果并存储到 useState(markers)。它可以工作,但是,当我想通过单击按钮删除位置结果时,它不起作用。我应该怎么做才能制作一个删除按钮。谢谢
我的 Map.js/App.js
import React, { useState, useEffect, useRef } from "react";
import {
GoogleMap,
useJsApiLoader,
Marker,
StandaloneSearchBox,
} from "@react-google-maps/api";
import Tablerecord from "../components/Tablerecord";
const libraries = ["places"];
const containerStyle = {
width: "100%",
height: "400px",
};
const inputStyle = {
width: "100%",
height: "500px",
};
const center = {
lat: 22.7658314,
lng: -22.4137297,
};
const options = {
disableDefaultUI: true,
zoomControl: true,
};
function App() {
const [markers, setMarkers] = useState([]);
const searchBox = useRef(null);
const [searchPlaceCenter, setSearchPlaceCenter] = useState([
parseFloat(43.7658314),
parseFloat(-79.4137297),
]);
const { isLoaded } = useJsApiLoader({
id: "google-map-script",
googleMapsApiKey: "API-KEY",
libraries,
});
return isLoaded ? (
<div>
<StandaloneSearchBox
onLoad={(ref) => (searchBox.current = ref)}
onPlacesChanged={async (event) => {
await // Find the search field value and make it be center value.
setSearchPlaceCenter([
parseFloat(
searchBox.current.getPlaces()[0].geometry.location.lat()
),
parseFloat(
searchBox.current.getPlaces()[0].geometry.location.lng()
),
]);
// Store Search geolocation value to useState markers for Red markers
setMarkers((current) => [
...current,
{
lat: searchBox.current.getPlaces()[0].geometry.location.lat(),
lng: searchBox.current.getPlaces()[0].geometry.location.lng(),
name: searchBox.current.getPlaces()[0].formatted_address,
time: new Date(),
},
]);
}}
>
<input
type="text"
name="address"
placeholder="Search Address"
autoComplete="off"
style={{
boxSizing: `border-box`,
}}
></input>
</StandaloneSearchBox>
<GoogleMap
mapContainerStyle={containerStyle}
zoom={8}
// Set center to searchPlace location to change center
center={{
lat: parseFloat(searchPlaceCenter[0]),
lng: parseFloat(searchPlaceCenter[1]),
}}
options={options}
>
{markers.map((marker) => (
<Marker
key={marker.time.toISOString()}
position={{
lat: parseFloat(marker.lat),
lng: parseFloat(marker.lng),
}}
/>
))}
</GoogleMap>
{/* !!!!!!!!Here is my question !!!!!!*/}
{markers.map((marker) => (
<div>
<Tablerecord key={marker.time} marker={marker} />
</div>
))}
</div>
) : (
<div>Loading...</div>
);
}
export default React.memo(App);
我的 Tablerecord.js(组件)
import React, { useState } from "react";
import styles from "../styles/tablerecord.module.css";
const Tablerecord = (marker,{markers,setMarkers}) => {
const handleRemoveLocation = (e) => {
const name = e.target.getAttribute("name");
console.log(markers) // undefined
setMarkers(markers.filter((item) => item.name !== name));
};
return (
<div className={styles.table}>
<center>
{/* This work, can show name,lat and lng */}
<p name={marker.marker.name}>Name: {marker.marker.name}</p>
<p>
lat: {marker.marker.lat}, lng: {marker.marker.lng}, Added Time:{" "}
{marker.marker.time.toTimeString()}
</p>
{/* Delete button I want to ask */}
<button name={marker.name} onClick={handleRemoveLocation}>
x
</button>
</center>
</div>
);
};
export default Tablerecord;
3个回答
您已经接近了,但还没有完全将正确的道具发送到表格记录组件。
<Tablerecord key={marker.time} marker={marker} markers={markers} setMarkers={setMarkers} />
然后,
const Tablerecord = (props) => {
const { marker, markers, setMarkers } = props;
// ...
}
或者如果你愿意:
const Tablerecord = ({ marker, markers, setMarkers }) => {
// ...
}
John Detlefs
2022-05-09
感谢以上所有评论!
最后,我调整了“Tablerecord”组件的代码和“Map.js”的一些代码。
这是我的代码
Tablerecord.js(组件)
import React, { useState } from "react";
import styles from "../styles/tablerecord.module.css";
const Tablerecord = ({ marker, markers, setMarkers }) => {
const handleRemoveLocation = (e) => {
const name = e.target.getAttribute("name");
// markers will output an Object to use .filter
// filter out the item which is equal to the name.
setMarkers(markers.filter((item) => item.name !== name));
};
return (
<div className={styles.table}>
<center>
{/* String type - name , lat, lng and time */}
<p>Name: {marker.name}</p>
<p>
lat: {marker.lat}, lng: {marker.lng}, Added Time:{" "}
{marker.time.toTimeString()}
</p>
{/* marker.name can let setMarkers detect the name */}
<button name={marker.name} onClick={handleRemoveLocation}>
x
</button>
</center>
</div>
);
};
export default Tablerecord;
Map.js
<Tablerecord key={marker.time} marker={marker} markers={markers} setMarkers={setMarkers} />
Lovelyzombie
2022-05-09
我相信您需要将状态添加到组件中
<Tablerecord key={marker.time} marker={marker} markers={markers} setMarkers={setMarkers} />
gavin
2022-05-09