编码新手,我正在尝试为谷歌地图创建一个搜索栏,其中输入查询(在 Search.js 中)将导致标记根据输入的内容(在 Map.js 中)过滤掉。
我很好地返回了过滤数组(filteredList),但是当我尝试将其设置为任何状态(places 或 newPlaces)时,它会以无限循环返回。
提前致谢。
App.js
import Map from './components/map/Map';
import Navbar from './components/Navbar';
class App extends Component {
constructor(props) {
super(props);
this.state = {
letters: '',
newPlaces: '',
places: [
{
name: "PL",
lat: 51.510228,
lng: -0.132992,
type: "alive"
},
...
]
}
this.searchState=this.searchState.bind(this)
};
// set the state of letters to match the Search.js input field
searchState = (e) => {
this.setState({letters: e}, this.handleSubmit)
}
// compare the filtered array with the original array in state and kick out the members of state.places that are missing in the filtered array
searchAdjustedArray = () => {
const filteredList = this.state.places.filter(club =>
club.name.toUpperCase().includes(this.state.letters.toUpperCase())
);
// here, is where either the places array must be ammended and pasted into Map as prop, or a new array - newPlaces, must be ammended, and passed as props into map.. infinit loops
this.setState({ newPlaces: filteredList })
}
render() {
return (
<div>
<Navbar
childMethodToChangeState={this.searchState}
/>
{this.searchAdjustedArray()}
<Map
markers={this.state.newPlaces}
/>
</div>
);
}
}
export default App;
其中输入字段是 Navbar.js 的组件
import Search from '../components/Search';
const Navbar = ({ childMethodToChangeState }) => {
return (
<nav className="d-flex navbar-expand-lg navbar-light bg-light">
<a className="navbar-brand" href="www.sassyladancer.com">Sassy's</a>
<button className="navbar-toggler"
type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle Navigation">
<span className="navbar-toggler-icon"></span>
</button>
<div className="collapse navbar-collapse" id="navbarSupportedContent">
<ul className="navbar-nav mr-auto">
<li className="nav-item">
<a className="nav-link" href="#">Reviews</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Testimonials</a>
</li>
<li className="nav-item">
<a className="nav-link" href="#">Special Offers</a>
</li>
</ul>
<form className="form-inline my-2 my-lg-0">
<Search
childMethodToChangeState={childMethodToChangeState}
/>
<button className="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
</nav>
);
}
export default Navbar;
搜索.js
const Search = ({ childMethodToChangeState }) => {
const [text, setText] = useState('')
const searchChange = (q) => {
setText(q)
childMethodToChangeState(q)
}
return (
<section className='search'>
<form>
<input
type='text'
className='form-control'
placeholders='Search Clubs'
value={text}
onChange={(e) => searchChange(e.target.value)}
autoFocus
/>
</form>
</section>
)
}
export default Search;
Map.js
import React, { Component } from 'react';
import { compose, withProps } from 'recompose';
import {
withScriptjs,
withGoogleMap,
GoogleMap,
Marker,
} from 'react-google-maps';
import icon1 from '../map/icon1.svg';
import iconDead from '../map/iconDead.svg';
const API = 'AIzaSyD_INqSpFnl3D3qLAq-jomYcYkztdUbCk0';
const MapWithMarkers = compose(
withProps({
googleMapURL: `https://maps.googleapis.com/maps/api/js?key=${API}&callbak=initMap`,
loadingElement: <div style={{ height: `100%` }} />,
containerElement: <div style={{ height: `800px` }} />,
mapElement: <div style={{ height: `100%` }} />,
}),
withScriptjs,
withGoogleMap,
)((props) =>
<GoogleMap
center={{ lat: 51.510228, lng: -0.132992 }}
zoom={10}
defaultOptions={{
styles: mapStyles
}}
>
{props.markers.map(place => {
return (
<MarkerWithSearch
key={place.id}
position={{ lat: place.lat, lng: place.lng }}
content={place.name}
icon={place.type}
/>
);
})}
</GoogleMap>
);
class MarkerWithSearch extends Component {
constructor() {
super();
this.state = {
isOpen: false
}
this.onToggleOpen = this.onToggleOpen.bind(this);
}
onToggleOpen() {
this.setState({
isOpen: !this.state.isOpen
});
}
render() {
return (
<Marker
id={this.props.id}
position={this.props.position}
onClick={this.onToggleOpen}
icon={ this.props.icon === "alive" ?
({
url: icon1,
scaledSize: new window.google.maps.Size(45, 45)
}) :
({
url: iconDead,
scaledSize: new window.google.maps.Size(45, 45)
})}
>
</Marker>
)
}
}
最佳答案
当您调用 setstate 时,它将触发渲染。在你的 App.js 中,你在每个渲染中调用 setstate,这就是你有无限循环的原因。 您可以通过此更改您的代码
import Map from './components/map/Map';
import Navbar from './components/Navbar';
class App extends Component {
constructor(props) {
super(props);
this.state = {
letters: '',
newPlaces: '',
places: [
{
name: "PL",
lat: 51.510228,
lng: -0.132992,
type: "alive"
},
...
]
}
this.searchState=this.searchState.bind(this)
};
// set the state of letters to match the Search.js input field
searchState = (e) => {
this.setState({letters: e}, this.handleSubmit)
}
// compare the filtered array with the original array in state and kick out the members of state.places that are missing in the filtered array
searchAdjustedArray = () => {
const filteredList = this.state.places.filter(club =>
club.name.toUpperCase().includes(this.state.letters.toUpperCase())
);
// here, is where either the places array must be ammended and pasted into Map as prop, or a new array - newPlaces, must be ammended, and passed as props into map.. infinit loops
this.setState({ newPlaces: filteredList })
}
render() {
useEffect( this.searchAdjustedArray,
[this.state.places, this.state.letters]
);
return (
<div>
<Navbar
childMethodToChangeState={this.searchState}
/>
<Map
markers={this.state.newPlaces}
/>
</div>
);
}
}
export default App;
关于reactjs - 错误 : Maximum update depth exceeded. 当组件在尝试 setState 时重复调用...无限循环时,可能会发生这种情况,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62864640/