reactjs - 错误 : Maximum update depth exceeded. 当组件在尝试 setState 时重复调用...无限循环时,可能会发生这种情况

标签 reactjs infinite-loop

编码新手,我正在尝试为谷歌地图创建一个搜索栏,其中输入查询(在 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/

相关文章:

javascript - 在reactjs上从父级的onClick更新状态子级

计算e^x的值

javascript - Angular 无限 $digest 循环

c++ - 当 int =(不是整数的东西)时停止无限循环

reactjs - 如何让爬虫知道在 Gatsby React 中重定向页面

reactjs - NextAuth 凭据未保存状态

javascript - ReactJS : Failed to load plugin 'testing-library' declared in 'package.json : Cannot find module ' ./eslint-utils'

Java Timer.Schedule(无限循环)停止运行

c# - 如何在不挂起程序的情况下运行无限循环? (C#)

javascript - Bootstrap : Responsive Image in Panel