Pet*_* G. 15 listview state android-mapview reactjs react-native
在以下示例中:
MapView
显示ListView
作为注释的元素ListView
元素应导致画吧蓝颜色.MapView
并且ListView
有效地使用状态对象在修改属性时,修改DataSource
of ListView
似乎会导致冲突active
:
您试图在对象上设置值为'active'且值为'false',该对象是不可变的并且已被冻结.
设置国家的正确方法是什么?
'use strict';
import React, {Component} from 'react';
import {AppRegistry,View,ListView,MapView,Text,TouchableOpacity} from 'react-native';
var annotations = [
{
title: 'A',active: false,latitude: 45,longitude: 26,latitudeDelta: 0.015,longitudeDelta: 0.015,
},{
title: 'B',active: false,latitude: 49,longitude: 14,latitudeDelta: 0.015,longitudeDelta: 0.015,
},{
title: 'C',active: false,latitude: 26,longitude: 25,latitudeDelta: 0.015,longitudeDelta: 0.015,
}
]
class SampleApp extends Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
this.state = {
region: annotations[0],
annotations: annotations,
dataSource: ds.cloneWithRows(annotations)
};
}
handleClick(field) {
if (this.previousField) {
this.previousField.active = false;
}
this.previousField = field;
field.active = true;
this.setState({
region: field,
});
}
renderField(field) {
let color = (field.active == true)?'blue':'yellow';
return (
<TouchableOpacity onPress={this.handleClick.bind(this,field)}>
<Text style={{backgroundColor:color,borderWidth:1}}>{field.title}</Text>
</TouchableOpacity>
);
}
render() {
return (
<View style={{flex:1,flexDirection:'column',alignSelf:'stretch'}}>
<MapView
style={{flex:0.5,alignSelf:'stretch',borderWidth:1}}
region={this.state.region}
annotations={this.state.annotations}
/>
<ListView
dataSource={this.state.dataSource}
renderRow={(field) => this.renderField(field)}
/>
</View>
);
}
}
AppRegistry.registerComponent('SampleApp', () => SampleApp);
Run Code Online (Sandbox Code Playgroud)
Mic*_*vey 23
问题
当您设置field.active = true;
或者this.previousField.active = false;
,您正在修改field
您的数据源中存在的对象()ListView
.的ListView
,因为当你创建它使用冻结其数据源引发错误cloneWithRows
.这是为了确保不能在正常的React组件生命周期之外修改数据源(如setState
).相反,ListView.DataSource
对象设计为使用更改cloneWithRows
,返回现有数据源的副本.
如果您熟悉Redux库,那么它与使用reducer函数返回状态副本而不是修改现有状态的理念非常相似.
克隆DataSource
要解决这个问题,不要改变函数中的field
对象,而是handleClick
要创建一个已设置值的新数据数组(如active
),然后setState
使用新ListView
创建的数据源调用cloneWithRows
.如果你这样做,你甚至根本不需要annotations
你所在州的钥匙.
代码可能比这里的文字更有帮助:
handleClick(field) {
//iterate over annotations, and update them.
//I'm taking 'title' as a unique id property for each annotation,
//for the sake of the example.
const newAnnotations = annotations.map(a => {
//make a copy of the annotation. Otherwise you'll be modifying
//an object that's in your listView's datasource,
//and therefore frozen.
let copyA = {...a};
if (copyA.title === field.title) {
copyA.active = true;
} else {
copyA.active = false;
}
return copyA;
});
this.setState({
region: {...field, active: true},
dataSource: this.state.dataSource.cloneWithRows(newAnnotations),
});
}
Run Code Online (Sandbox Code Playgroud)
我希望这有帮助!这是一个代码片段,其中包含您发布的完整代码以及我的修改.正如你在iOS上使用React Native 0.29所描述的那样,它正在为我工作.你标记了android-mapview的问题,所以我假设你正在运行Android,但在这种情况下平台不应该真正有所作为.
'use strict';
import React, {Component} from 'react';
import {AppRegistry,View,ListView,MapView,Text,TouchableOpacity} from 'react-native';
var annotations = [
{
title: 'A',active: false,latitude: 45,longitude: 26,latitudeDelta: 0.015,longitudeDelta: 0.015,
},{
title: 'B',active: false,latitude: 49,longitude: 14,latitudeDelta: 0.015,longitudeDelta: 0.015,
},{
title: 'C',active: false,latitude: 26,longitude: 25,latitudeDelta: 0.015,longitudeDelta: 0.015,
}
]
class SampleApp extends Component {
constructor(props) {
super(props);
var ds = new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
});
this.state = {
region: annotations[0],
dataSource: ds.cloneWithRows(annotations)
};
}
handleClick(field) {
//iterate over annotations, and update them.
//I'm taking 'title' as a unique id property for each annotation,
//for the sake of the example.
const newAnnotations = annotations.map(a => {
//make a copy of the annotation. Otherwise you'll be modifying
//an object that's in your listView's datasource,
//and therefore frozen.
let copyA = {...a};
if (copyA.title === field.title) {
copyA.active = true;
} else {
copyA.active = false;
}
return copyA;
});
this.setState({
region: {...field, active: true},
dataSource: this.state.dataSource.cloneWithRows(newAnnotations),
});
}
renderField(field) {
console.log(field);
let color = (field.active == true)?'blue':'yellow';
return (
<TouchableOpacity onPress={this.handleClick.bind(this,field)}>
<Text style={{backgroundColor:color,borderWidth:1}}>{field.title}</Text>
</TouchableOpacity>
);
}
render() {
return (
<View style={{flex:1,flexDirection:'column',alignSelf:'stretch'}}>
<MapView
style={{flex:0.5,alignSelf:'stretch',borderWidth:1}}
region={this.state.region}
annotations={this.state.annotations}
/>
<ListView
dataSource={this.state.dataSource}
renderRow={(field) => this.renderField(field)}
/>
</View>
);
}
}
AppRegistry.registerComponent('SampleApp', () => SampleApp);
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
15105 次 |
最近记录: |