超过最大更新深度-React

时间:2019-01-13 20:45:25

标签: javascript reactjs

我正在构建一个React应用程序,其中用户输入搜索词,后端提供json数组。在结果页面上,我正在尝试实施分面搜索,因此我没有几个过滤器。我正在根据用户选择的复选框过滤获取的结果。这是UI。 enter image description here

这是我的搜索结果页面的js文件。

import React from 'react';
import NavigationBar from './NavigationBar';
import SearchPageResultsStyle from "../assets/css/SearchResultsPage.css"
import Pagination from './Pagination';

class SearchResultsPage  extends React.Component{
    constructor(props) {
        super(props);
        this.state = {
            results: this.props.location.state.data.results,
            keyword: this.props.location.state.data.keyword,
            pageOfItems: [],
            cities: {
                'New York City (NYC)': false,
                'Delhi': false,
                'Bangkok': false,
                'Paris': false,
                'Mexico City': false
            },
            topics: {
                'Environment': false,
                'Crime': false,
                'Politics': false,
                'Social Unrest': false,
                'Infrastructure': false
            },
            languages: {
                'Hindi': false,
                'English': false,
                'Thai': false,
                'French': false,
                'Spanish': false
            }
        };
        this.onChangePage = this.onChangePage.bind(this);
        this.onCityChange = this.onCityChange.bind(this);
    }

    componentDidUpdate(prevProps, prevState) {
        if (prevState !== this.state) {
            console.log(this.state.cities);
            const filteredCities = [];
            for (let key in this.state.cities) {
                if (this.state.cities[key] === true) {
                    filteredCities.push(key)
                }
            }
            console.log(filteredCities);
            const filteredResults = [];
            this.state.results.forEach((result) => {
                for (let i = 0; i < filteredCities.length; i++) {
                    if (result.city === filteredCities[i]) {
                        filteredResults.push(result)
                    }
                }
            })
            console.log("fileterdPageOfItems", filteredResults)
            this.updatePageOfItems(filteredResults)

        }
    }

    // Function to filter the search results based on user chosen filters
    updatePageOfItems(filteredResults) {
        this.setState({
            results: filteredResults
        })
    }

    onChangePage(pageOfItems) {
        // update local state with new page of items
        this.setState({pageOfItems});
    }

    // setting each city in cities object (city chechboxes which are clicked on UI) to true
    onCityChange(e) {
        const val = e.target.checked;
        const name = e.target.name;
        let updatedCities = Object.assign({},this.state.cities,{[name]: val});
        this.setState({
            cities: updatedCities,
        })
    }

    // rendering checkboxes for cities
    renderCity() {
        const cities = ['New York City (NYC)','Delhi','Bangkok','Paris','Mexico City']
        return cities.map((city,i) => {
            return (
                <div>
                    <label key={i}>
                        {city}
                        <input
                            type="checkbox"
                            name={city}
                            onChange={this.onCityChange}
                            value={this.state.cities[city]}/>
                    </label>
                </div>

            )
        })
    }

    render() {

        const renderItems = this.state.pageOfItems.map((item, index) => {
            return (
                <div>
                    <h3 style={{color: '#1a0dab'}} key={index}>{item.text}</h3>
                    <a href={'https://google.com'} key={index}>{item.tweetUrl}</a>
                    <br/>
                    <p><span style={{fontWeight:'bold', textColor:'#6a6a6a'}} key={index}>topic: </span>{item.topic}</p>
                    <p><span style={{fontWeight:'bold', textColor:'#6a6a6a'}} key={index}>city: </span>{item.city}</p>
                    <p><span style={{fontWeight:'bold', textColor:'#6a6a6a'}} key={index}>lang: </span>{item.lang}</p>
                    <p><span style={{fontWeight:'bold', textColor:'#6a6a6a'}} key={index}>Hashtags: </span></p>
                    <hr/>
                </div>
            )
        });

        return (
            <div>
                <NavigationBar/>
                <h4 style={{textAlign:'center', color:'#1a0dab'}}>Showing search results for <span style={{fontWeight:'bold', fontStyle:'Italic'}}>'{this.state.keyword}'</span></h4>
                <hr/>
                <div className={'wrap'} style={SearchPageResultsStyle}>
                    <div className={'fleft'}>
                        <h4>City</h4>
                        {this.renderCity()}
                        <hr/>
                        <h4>Topics</h4>
                        <hr/>
                        <h4>Language</h4>
                        <hr/>
                    </div>
                    <div className={'fcenter'}>
                        {renderItems}
                        <Pagination items={this.state.results} onChangePage={this.onChangePage}/>
                    </div>
                    <div className={'fright'}></div>
                </div>
            </div>
        )
    }

}

export default SearchResultsPage;

每当用户单击特定的复选框时,我都会将状态中的城市更新为true,然后根据阵列filteredCities中的城市过滤(从后端)提取的结果,并进行收集过滤后的结果放入数组filteredResults中,然后将该数组传递给函数updatePageOfItems来更改状态,以便可以重新渲染过滤后的结果。但是,当我调用函数updatePageOfItems时,应用程序进入了无限循环。 解决此问题的方法是什么?我是第一次来面对这个问题的新手。

这是堆栈跟踪 enter image description here

1 个答案:

答案 0 :(得分:0)

我能够解决此问题,而不是在函数componentDidUpdate中过滤结果,而是在setState函数内的onCityChange的回调函数中进行了操作。

onCityChange(e) {
        const val = e.target.checked;
        const name = e.target.name;
        let updatedCities = Object.assign({},this.state.cities,{[name]: val});
        this.setState({
            cities: updatedCities,
        },function () {
            const filteredCities = [];
            for (let key in this.state.cities) {
                if (this.state.cities[key] === true) {
                    filteredCities.push(key)
                }
            }
            console.log("filteredCities", filteredCities);
            const filteredResults = [];
            this.state.results.forEach((result) => {
                for (let i = 0; i < filteredCities.length; i++) {
                    if (result.city === filteredCities[i]) {
                        filteredResults.push(result)
                    }
                }
            })
            this.setState({
                results: filteredResults
            },function () {
                console.log(this.state.results)
            })
        })
    }