首页 > 解决方案 > 反应太多的重新渲染,不确定原因

问题描述

我正在构建一个组件来搜索一些站点,这些站点只是一些专有数据对象,并且它可以访问 api。我有一个分页组件,因为有很多网站。当我导航到另一个页面时,我得到一个不变的违规错误。但我真的不知道为什么。

这是有问题的反应组件:

export default class SiteSearch extends React.Component<ISiteSearchProps, ISiteSearchState> {
  constructor(props: ISiteSearchProps) {
    super(props);
    this.state = {
      pageLimit: 10,
      page: 0,
      searchProperty: [],
      searchTerm: '',
      siteSearchResult: {
        total: 0,
        sites: undefined
      }
    };
  }

  searchForSite = async () => {
    const searchRequest: ISiteSearchRequest = {
      pageLimit: this.state.pageLimit,
      page: this.state.page,
      searchProperty: this.state.searchProperty,
      searchTerm: this.state.searchTerm
    };

    try {
      if (searchRequest.pageLimit && searchRequest.searchTerm && searchRequest.searchProperty.length > 0) {
        const response = await siteService.searchSites(this.props.user, searchRequest);
        this.setState({
          siteSearchResult: response
        });
      }
    } catch (e) {
      console.log(e);
    }
  }

  updateSearchTerm = (searchTerm: string) => {
    this.setState({
      searchTerm
    });
  }

  updateSearchProperty = (selection: ISelections[]) => {
    if (selection.length > 0) {
      this.setState({
        searchProperty: selection
      });
    } else {
      this.setState({
        searchProperty: []
      });
    }
  }

  renderSearchPropertyOptions = () => {
    return searchValues.map((val: string, key: number) => {
      return <DropdownOption key={key} label={FriendlySearchProperties[val]} value={val} />;
    });
  }

  onGotoPage = (page: number) => {
    this.setState({
      page
    });

    this.searchForSite();
  }

  renderDataGrid = () => {
    if (this.state.siteSearchResult.sites) {
      const columns: DatagridColumnDef[] = [
        {fieldKey: 'country', title: 'Country'},
        {fieldKey: 'city', title: 'City' }
      ];
  
      const data: DatagridRow[] = this.state.siteSearchResult.sites.map((p, i) => {
        return {
          fields: {
            country: p.country,
            city: p.city
          }
        };
      });

      return (
        <>
          <div className='row searchHeaderText'>
          <span className='col-xs-12'>
            <h4>List of Sites: </h4>
          </span>
          </div>
          <div className='row'>
            <div className='col-xs-12'>
              <Datagrid
                columns={columns}
                data={data}
                page={this.state.page}
                pageSize={this.state.pageLimit}
                rowHeight='small' 
                zebraColoring={true}
                enableSorting={false}
                style={{height: '250px', margin: '10px 0 10px 0', borderTop: '1px solid black', borderRight: '1px solid black', borderLeft: '1px solid black'}}
              />
            </div>
          </div>
          <div className='row'>
            <div className='col-xs-12'>
              <Pagination
                style={{ marginTop: '8px' }}
                onGotoPage={this.onGotoPage}
                rowCount={this.state.siteSearchResult.total === 0 ? 1 : this.state.siteSearchResult.total}
                currentPage={this.state.page}
                currentPageSize={this.state.pageLimit}
              />
            </div>
          </div>
        </>
      );
    } else {
      return null;
    }
  }

  render() {
    const disableSearch = this.state.searchTerm === '' || this.state.searchProperty.length === 0;

    return (
      <div className='row searchContainer'>
        <div className='row searchControlsContainer'>
          <Input
            className='searchTermInput col-xs-7'
            value={this.state.searchTerm}
            onValueChange={this.updateSearchTerm}
            dataType='text'
          />
          <Dropdown value={this.state.searchProperty} onChange={this.updateSearchProperty} className='searchPropertySelect col-xs-3'>
            {this.renderSearchPropertyOptions()}
          </Dropdown>
          <Button disabled={disableSearch} onClick={() => this.searchForSite()} sizeClass='small' className='searchButton' icon='abb/search'/>
        </div>
        <div className='row searchHeaderText'>
          <span className='col-xs-12'>
            <h4>Site Selected: </h4>
          </span>
        </div>
        {this.renderDataGrid()}
      </div>
    );
  }
}

分页所做的就是调用 onGotoPage 方法,我不确定为什么会导致太多的重新渲染。

标签: reactjstypescriptpagination

解决方案


我认为你有一个永无止境的循环

Pagination呼叫onGotoPageonGotoPage呼叫searchForSiteAND setStatesearchForSite也呼叫setState。调用setState将触发重新渲染并在renderonGotoPage再次调用。所以这会发生,直到 React 变得无聊(不是真的,直到它做了太多的重新渲染)

您需要在某处断开链接。不要不断地调用setState自己的方法或方法;setState

尝试利用componentDidMount或重构您的代码,使其不会连续执行此最大状态循环


推荐阅读