gpt4 book ai didi

javascript - React Redux-子组件不会在状态更改时重新渲染

转载 作者:行者123 更新时间:2023-11-29 20:58:34 27 4
gpt4 key购买 nike

架构是这样的:我有一个plotMap组件,它从状态中获取绘图列表并将它们映射到一堆 plotMarker基于 map 缩放(也从状态读取)返回多边形/标记的组件。如果选择给定的图进行编辑,plotMarker组件返回 plotPolygon可编辑的组件。当用户保存编辑后的 ​​plotPolygon组件,这会更新状态图列表中的相应图。

问题:plotMarker的多边形,编辑后立即显示 plotPolygon组件已成功保存,不会更新为新形状,而是保留旧形状。只有当一个缩小时,plotMarker呈现其标记组件,然后放大,然后 plotMarker再次渲染其多边形组件,是否显示新形状。

这可能是由于应用程序内部滞后造成的吗?我怎样才能制作 plotMarker保存成功后立即显示新的多边形?

plotMap 组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import { Map, TileLayer, LayersControl, MapControl } from 'react-leaflet';
import { GoogleLayer } from './GoogleLayer';
import { geolocated } from 'react-geolocated';
import 'leaflet-geocoder-mapzen';
import SearchBox from './searchBox';
import Control from 'react-leaflet-control';
import { centroid } from '@turf/turf';
import PlotMarker from './plotMarker';

const { BaseLayer } = LayersControl;
const key = 'key';
const hybrid = 'HYBRID';
const terrain = 'TERRAIN';
const road = 'ROADMAP';
const satellite = 'SATELLITE';

const centerLat = props => {
if (
props.isGeolocationAvailable &&
props.isGeolocationEnabled &&
props.coords
) {
return props.coords.latitude;
}
return 32.11;
};

const centerLong = props => {
if (
props.isGeolocationAvailable &&
props.isGeolocationEnabled &&
props.coords
) {
return props.coords.longitude;
}
return 34.963;
};

const mapCenterPoint = props => {
if (props.plots && (props.selectedPlot || props.plotBeingEdited)) {
let ourPlot = props.plots.filter(
plot => plot._id === (props.selectedPlot || props.plotBeingEdited)
)[0];
try {
let center = centroid(ourPlot.feature).geometry.coordinates.reverse();
return { center: center, zoom: 16 };
} catch (e) {
console.log(e);
}
}
return { center: [centerLat(props), centerLong(props)], zoom: 8 };
};

export class PlotMap extends Component {
markers = props => {
if (props.plots) {
return (
<div>
{(props.filteredPlots || props.plots).map(
plot =>
plot &&
plot.feature &&
plot._id && (
<PlotMarker
key={plot._id}
id={plot._id}
name={plot.name}
geoJSON={plot.feature}
/>
)
)}
</div>
);
}
};

render() {
return (
<div
className="col-sm-8 m-auto p-0 flex-column float-right"
style={{ height: `85vh` }}>
<Map
center={mapCenterPoint(this.props).center}
zoom={mapCenterPoint(this.props).zoom}
zoomControl={true}
onZoomend={e => {
this.props.setZoomLevel(e.target.getZoom());
}}
onMoveEnd={e => {
this.props.setMapCenter(e.target.getCenter());
}}>
<LayersControl position="topright">
<BaseLayer name="Google Maps Roads">
<GoogleLayer googlekey={key} maptype={road} />
</BaseLayer>
<BaseLayer name="Google Maps Terrain">
<GoogleLayer googlekey={key} maptype={terrain} />
</BaseLayer>
<BaseLayer checked name="Google Maps Hybrid">
<GoogleLayer
googlekey={key}
maptype={hybrid}
libraries={['geometry', 'places']}
/>
</BaseLayer>
</LayersControl>
<SearchBox postion="bottomright" />
{this.markers(this.props)}
</Map>
</div>
);
}
}

function mapStateToProps(state) {
return {
filteredPlots: state.plots.filteredPlots,
plots: state.plots.plots,
selectedPlot: state.plots.selectedPlot,
mapCenter: state.plots.mapCenter
};
}

export default geolocated({
positionOptions: {
enableHighAccuracy: false
},
userDecisionTimeout: 5000,
suppressLocationOnMount: false
})(connect(mapStateToProps, actions)(PlotMap));

plotMarker 组件:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import { Marker, Popup, GeoJSON } from 'react-leaflet';
import { centroid } from '@turf/turf';
import PlotPolygon from './plotPolygon';

const position = geoJSON => {
return centroid(geoJSON).geometry.coordinates.reverse();
};

export class PlotMarker extends Component {
render() {
const {
id,
name,
geoJSON,
zoomLevel,
selectedPlot,
plotBeingEdited
} = this.props;
const markerPosition = position(geoJSON);
let style = () => {
return {
color: 'blue'
};
};
if (selectedPlot === id) {
style = () => {
return {
color: 'red'
};
};
}
if (zoomLevel > 14 && plotBeingEdited === id) {
return <PlotPolygon id={id} geoJSON={geoJSON} />;
} else if (zoomLevel > 14) {
return (
<GeoJSON
id={id}
data={geoJSON}
style={style}
onClick={() => {
this.props.selectPlot(id);
}}
/>
);
}
return (
<Marker
id={id}
className="marker"
position={markerPosition}
onClick={() => {
this.props.selectPlot(id);
}}>
<Popup>
<span>{name}</span>
</Popup>
</Marker>
);
}
}

function mapStateToProps(state) {
return {
selectedPlot: state.plots.selectedPlot,
plotBeingEdited: state.plots.plotBeingEdited,
zoomLevel: state.plots.zoomLevel,
plots: state.plots.plots,
filteredPlots: state.plots.filteredPlots
};
}

export default connect(mapStateToProps, actions)(PlotMarker);

plotPolygon 组件

import React, { Component } from 'react';
import { connect } from 'react-redux';
import * as actions from '../../actions';
import { Polygon, FeatureGroup } from 'react-leaflet';
import { EditControl } from 'react-leaflet-draw';

const positions = props => {
return props.geoJSON.geometry.coordinates[0].map(a => [a[1], a[0]]);
};

export class PlotPolygon extends Component {
render() {
const { id, geoJSON } = this.props;
return (
<FeatureGroup>
<EditControl
position="topright"
onEdited={e => {
e.layers.eachLayer(a => {
this.props.updatePlot({
id: id,
feature: a.toGeoJSON()
});
});
}}
edit={{ remove: false }}
draw={{
marker: false,
circle: false,
rectangle: false,
polygon: false,
polyline: false
}}
/>
<Polygon positions={[positions(this.props)]} />;
</FeatureGroup>
);
}
}

function mapStateToProps(state) {
return { plots: state.plots.plots, filteredPlots: state.plots.filteredPlots };
}

export default connect(mapStateToProps, actions)(PlotPolygon);

最佳答案

原始解决方案:

退出编辑模式后是否需要重置缩放级别?您的逻辑在 mapCenterPointplotMarkerif(zoomLevel... 部分之间紧密耦合。我想知道您是否有导致它在编辑后(直到手动缩放)始终评估为真的状态:props.plots && (props.selectedPlot || props.plotBeingEdited)


重构思考:

to figure out a more elegant way

选项 1:HOC

高阶组件(或 HOC)可能是一个很好的方法。您的代码中已有一个 HOC 示例:

export default connect(mapStateToProps, actions)(PlotMarker);

在 React 世界中,HOC 实际上只是返回对您有用的东西的函数。因此,它们是一种很好的代码重用形式。 connect 是一个 HOC,在这种情况下返回一个函数,但 HOC 通常用于返回组件。因此,您可能有一个像 plotMarker(zoomLevel, beingEdited) 这样的 HOC,它本身执行逻辑以确定要呈现哪种类型的标记组件。

查看React's Higher Order Component Documentation了解更多。


选项 2:单一返回声明

我一直热衷于对渲染方法使用单个返回语句。我没有深入研究 React 如何处理差异,但根据我的经验,我很确定它以这种方式响应更好 - 所以它可能不需要你调整缩放级别来重置它。

我将如何在一次返回中执行所有 PlotMarker 的逻辑:

export class PlotMarker extends Component{
render(){
const {
id,
name,
geoJSON,
zoomLevel,
selectedPlot,
plotBeingEdited
} = this.props;

const markerPosition = position(geoJSON);

let style = () =>{
return {
color: 'blue'
};
};
if(selectedPlot === id){
style = () =>{
return {
color: 'red'
};
};
}

return (
<div>
{
zoomLevel > 14 && plotBeingEdited === id &&
<PlotPolygon id={id} geoJSON={geoJSON}/> ||

zoomLevel > 14 &&
<GeoJSON
id={id}
data={geoJSON}
style={style}
onClick={() =>{
this.props.selectPlot(id);
}}
/> ||

<Marker
id={id}
className="marker"
position={markerPosition}
onClick={() => {
this.props.selectPlot(id);
}}>
<Popup>
<span>{name}</span>
</Popup>
</Marker>
}
</div>
);
}
}

关于javascript - React Redux-子组件不会在状态更改时重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47927335/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com