javascript-更新状态后,React组件表被渲染多次或重复

我通过替换旧状态来更新道具的状态.在渲染中,数据被复制或使用新道具重置后从该状态多次渲染.它是在第一次渲染之后发生的.

这是应用程序的工作流程-当用户搜索位置时,获取操作首先发生.它会在用户位置周围显示“推荐位置”.它将数据作为“推荐位置”放入redux存储.有问题的组件从商店渲染数据[第一张图片],这很好.单击过滤器按钮时,这次它将获取用户位置和过滤器,并将数据放入redux商店中,例如restaurant = [],bars = []等.组件应从商店中获取新数据,并重新渲染.那就是我的问题所在.重新渲染时,似乎在复制数据[第二张图片].

这是有问题的组件-

import React,{ Component } from "react";
import PropTypes from "prop-types";

export default class Results extends Component {
  state = {
    places: []
  };

getSnapshotBeforeUpdate(prevProps) {

  const {places,restaurant,bar,coffee,bank,park} = 
  this.props.results;

  if (prevProps.results.places !== places) {
      this.setState({ places });
  }
  if (prevProps.results.restaurant !== restaurant) {
      this.setState({ places: restaurant });
  }
  if (prevProps.results.bar !== bar) {
      this.setState({ places: bar });
  }
  if (prevProps.results.coffee !== coffee) {
      this.setState({ places: coffee });
  }
  if (prevProps.results.bank !== bank) {
      this.setState({ places: bank });
  }
  if (prevProps.results.park !== park) {
      this.setState({ places: park });
  }
}

renderPlaces = () => this.state.places.map((place,i) => {
  if (place.type || place.type === "Recommended Places") {
      return place.items.map((item,i) => (
          <tbody key={item.venue.id}>
              <tr className="table-secondary">
                  <th scope="row">{item.venue.name}</th>
                  <td>
                      <h6>
                          {`${(item.venue.location.distance / 
                           1609.344).toFixed(2)}`}{" "}
                          <cite>miles</cite>
                      </h6>
                  </td>
              </tr>
          </tbody>
      ));
  }
  return this.state.places.map((place,i) => (
      <tbody key={place.id}>
          <tr className="table-secondary">
              <th scope="row">{place.name}</th>
              <td>
                  <h6>
                      {`${(place.location.distance / 
                      1609.344).toFixed(2)}`}{" "}
                      <cite>miles</cite>
                  </h6>
              </td>
          </tr>
      </tbody>
   ));
})

render() {
  return (
      <React.Fragment>
          {this.renderPlaces()}
      </React.Fragment>
  );
 }
}

Results.propTypes = {
  places: PropTypes.array,restaurant: PropTypes.array,coffee: PropTypes.array,bar: PropTypes.array,banks: PropTypes.array,parks: PropTypes.array
};

以下是父组件-

import React,{ Component } from "react";
import PropTypes from "prop-types";

import { connect } from "react-redux";
import Results from "./Results";

class ResultList extends Component {
  state = {
    places: [],restaurant: [],bar: [],coffee: [],bank: [],park: []
  };

  getSnapshotBeforeUpdate(prevProps) {
    const {
      recommendedPlaces,restaurants,bars,banks,parks
    } = this.props;

    if (prevProps.recommendedPlaces !== recommendedPlaces) {
      this.setState({ places: recommendedPlaces });
      // returning a snapshot just in case I want to use..⬇
      // componentDidUpdate in the future
      return recommendedPlaces;
    }
    if (prevProps.restaurants !== restaurants) {
      this.setState({ restaurant: restaurants });
      // returning a snapshot just in case I want to use..⬇
      // componentDidUpdate in the future
      return restaurants;
    }
    if (prevProps.bars !== bars) {
      this.setState({ bar: bars });
      // returning a snapshot just in case I want to use..⬇
      // componentDidUpdate in the future
      return bars;
    }
    if (prevProps.coffee !== coffee) {
      this.setState({ coffee });
      // returning a snapshot just in case I want to use..⬇
      // componentDidUpdate in the future
      return coffee;
    }
    if (prevProps.banks !== banks) {
      this.setState({ bank: banks });
      // returning a snapshot just in case I want to use..⬇
      // componentDidUpdate in the future
      return banks;
    }
    if (prevProps.parks !== parks) {
      this.setState({ park: parks });
      // returning a snapshot just in case I want to use..⬇
      // componentDidUpdate in the future
      return parks;
    }

    return null;
  }

  render() {
    const { address,filterBy } = this.props;
    return (
      <table className="primary table table-hover">
        <thead>
          <tr>
            <th scope="col">
              {filterBy === null ? "Places" : filterBy.toUpperCase()}
              {
                // eslint-disable-next-line
              }{" "}
              near
              {
                // eslint-disable-next-line
              }{" "}
              {address.toUpperCase()}
            </th>
            {/* this.showPlaces(recommendedPlaces,parks) */}
            <th scope="col">Distance</th>
          </tr>
        </thead>
        <Results results={this.state} />
      </table>
    );
  }
}

ResultList.propTypes = {
  address: PropTypes.string,filterBy: PropTypes.string,recommendedPlaces: PropTypes.array,restaurants: PropTypes.array,bars: PropTypes.array,parks: PropTypes.array
};

const mapStateToProps = state => ({
  recommendedPlaces: state.places.recommendedPlaces,restaurants: state.places.restaurants,coffee: state.places.coffee,bars: state.places.bars,banks: state.places.banks,parks: state.places.parks
});

export default connect(mapStateToProps)(ResultList);

接下来的两张图片是渲染的页面.

第一个是我搜索位置时的第一个渲染.完美渲染.它仅获取并呈现“推荐地点”.

enter image description here

其次是单击左侧的过滤器按钮后,当新道具进入状态重置状态后发生的渲染.它不会过滤位置数据.相反,它使用位置和过滤器获取并呈现新数据.

enter image description here

任何帮助深表感谢!

https://codesandbox.io/s/zw33318484
在自动完成搜索字段中搜索地址.它应使用“推荐位置”呈现页面的中间(ResultList.js和Result.js).然后选择“餐厅”过滤器.现在,它应该重新渲染商店中的餐馆.相反,它只是继续在渲染中添加餐厅.我认为它正在重新渲染,并不断在道具中连接餐厅阵列.它做了很多次,所以重新渲染.

最佳答案
问题出在您的renderPlaces函数中.下面是简化版本,使您可以更轻松地查看结构.

renderPlaces = () => {
    this.state.places.map((place,i) => {
      if (place.type || place.type === "Recommended Places") {
          // When first selecting a location from the autocomplete search,// you execute this code
          return place.items.map((item,i) => (
              <tbody key={item.venue.id}>
                  {/* stuff to render a place */}
              </tbody>
          ));
      }
      // When you select a filter,you hit this condition instead.
      return this.state.places.map((place,i) => (
          <tbody key={place.id}>
              {/* stuff to render a place */}
          </tbody>
       ));
    })
};

首次选择位置时,在this.state.places中只有一个条目,其place.type为“ Recommended Places”.那个地方有一系列驱动渲染的项目.当您选择一个过滤器(例如“餐馆”)时,地点有多个条目(在我看到的情况下为10个),而且它们都没有类型,因此符合第二个条件.第二个返回执行this.state.places.map调用,但是您仍然在外部this.state.places.map调用内,因此您对每个位置都遍历所有位置一次.因此,多余的副本与重新渲染的数量无关,而仅与位数有关.如果您删除第二个this.state.places.map,如下所示,它将正常工作(至少在这方面).

renderPlaces = () => {
    this.state.places.map((place,i) => {
      if (place.type || place.type === "Recommended Places") {
          return place.items.map((item,i) => (
              <tbody key={item.venue.id}>
                  {/* stuff to render a place */}
              </tbody>
          ));
      }
      return (
          <tbody key={place.id}>
              {/* stuff to render a place */}
          </tbody>
      );
    })
};

Edit nearby

相关文章

kindeditor4.x代码高亮功能默认使用的是prettify插件,prett...
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代...
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小