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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


kindeditor4.x代码高亮功能默认使用的是prettify插件,prettify是Google提供的一款源代码语法高亮着色器,它提供一种简单的形式来着色HTML页面上的程序代码,实现方式如下: 首先在编辑器里面插入javascript代码: 确定后会在编辑器插入这样的代码: <pre
这一篇我将介绍如何让kindeditor4.x整合SyntaxHighlighter代码高亮,因为SyntaxHighlighter的应用非常广泛,所以将kindeditor默认的prettify替换为SyntaxHighlighter代码高亮插件 上一篇“让kindeditor显示高亮代码”中已经
js如何实现弹出form提交表单?(图文+视频)
js怎么获取复选框选中的值
js如何实现倒计时跳转页面
如何用js控制图片放大缩小
JS怎么获取当前时间戳
JS如何判断对象是否为数组
JS怎么获取图片当前宽高
JS对象如何转为json格式字符串
JS怎么获取图片原始宽高
怎么在click事件中调用多个js函数
js如何往数组中添加新元素
js如何拆分字符串
JS怎么对数组内元素进行求和
JS如何判断屏幕大小
js怎么解析json数据
js如何实时获取浏览器窗口大小
原生JS实现别踩白块小游戏(五)
原生JS实现别踩白块小游戏(一)