Я обновляю состояние с изменениями в реквизитах, заменяя старое состояние. При рендеринге данные либо дублируются, либо воспроизводятся несколько раз из состояния после сброса с новыми реквизитами. Это происходит после первого рендера.
Это рабочий процесс приложения - выборка происходит в первую очередь, когда пользователь ищет местоположение. Это получает "рекомендуемые места" вокруг местоположения пользователей. Это помещает данные в избыточное хранилище как «рекомендуемые места». Компоненты, о которых идет речь, визуализируют данные из хранилища [первая картинка], что происходит хорошо. Когда нажимаются кнопки фильтра, на этот раз он выбирает данные о местоположении пользователя и фильтре и помещает данные в хранилище избыточных данных, например, 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,
coffee,
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, restaurants, bars, 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,
coffee: PropTypes.array,
bars: PropTypes.array,
banks: 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);
Следующие две картинки являются отображаемой страницей.
Первый - первый рендер при поиске места. Рендеринг отлично. Он выбирает и отображает только «рекомендуемые места».
Второй - это рендеринг, который происходит после сброса состояния, когда появляются новые реквизиты при нажатии на кнопку фильтра слева. Он не фильтрует данные о местах. Вместо этого он выбирает и отображает новые данные с использованием местоположения и фильтра.
Любая помощь очень ценится!
https://codesandbox.io/s/zw33318484
Найдите адрес в поле поиска автозаполнения. Он должен отображать середину страницы (ResultList.js и Result.js) с «рекомендуемыми местами». Затем выберите «ресторанный» фильтр. Теперь следует перерисовать рестораны, которые находятся в магазине. Вместо этого он просто продолжает добавлять ресторан на визуализации. Я думаю, что это повторный рендеринг и объединение ресторанного массива в реквизитах. Он делает это столько раз, сколько перерисовывает.