我正在尝试实现一个选择器页面,用户可以在其中基于3个位置属性(设施,楼层,套房)选择室内地图。这3个属性的任何唯一组合都可以保证具有唯一的室内地图。我正在使用React Native的Picker下拉菜单供用户选择他们想要查看的设施,楼层和套房。在选择这些属性中的任何一个时,它应该过滤其余属性的选项,以便存在有效的组合。
过滤列表的算法对我来说不是问题。问题是,当我为其中一个选择器选择一个选择器值时,它将其他选择器的值重置为defaultPlacholder值'---',我无法弄清原因。
每个选择器的selectedValue等同于存储当前所选设施,楼层或套件ID的状态变量。状态变量一开始被初始化为“ defaultPlaceholder”。从下拉菜单中选择其他ID会调用setState更改当前选定ID的ID。至少这是我所期望的。
相反,当从onValueChange调用setState(状态变量)时,组件将重新渲染多次(而不是重新渲染一次),而不是重新渲染一次。状态变量将更改为所需的下拉项,以进行一次渲染迭代,然后自动重置为defaultPlaceholder值。不仅如此,即使某些选择器的状态变量没有更改,它也以某种方式触发了其他选择器的onValueChange,只有选择器项列表(例如pickerFacilitiesList)发生了变化。现在,无论之前的状态值是什么,其他选择器项都将重置为defaultPlaceholder值。
更令人困惑的是,套件选择器不会发生此问题,只有设施选择器和楼层选择器才会发生此问题。
任何帮助将不胜感激。
下面:render()函数的一部分
//.map iterates through uniqueFacilityIDs and generates a list of picker items
const pickerFacilitiesList = uniqueFacilityIDs.map(a => {
return <Picker.Item key={a.key} label={a.facilityName} value={a.facilityID} />;
});
const pickerFloorsList = uniqueFloorIDs.map(a => {
return <Picker.Item key={a.key} label={a.floorName} value={a.floorID} />;
});
const pickerSuitesList = uniqueSuiteIDs.map(a => {
return <Picker.Item key={a.key} label={a.suiteName} value={a.suiteID} />;
});
if(this.state.pickerFacilityID === defaultPlaceholder || this.state.pickerFloorID === defaultPlaceholder || this.state.pickerSuiteID === defaultPlaceholder){
return (
<View>
<Text style={{fontSize: 18, fontWeight: 'bold', textAlign: 'center', marginBottom: 25, marginTop: 15}}> Display Assets by Suites </Text>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30, marginBottom: 15, textDecorationLine: 'underline'}}>Filter suites by:</Text>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30}}> Facility </Text>
<Picker
mode = 'dropdown'
style = {{width: '80%', marginLeft: 30}}
selectedValue={this.state.pickerFacilityID}
onValueChange={(itemValue, itemIndex) => {
this.setState({pickerFacilityID:itemValue})
}}
>
<Picker.Item label = {defaultPlaceholder} value = {defaultPlaceholder}/>
{pickerFacilitiesList}
</Picker>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30}}> Floor </Text>
<Picker
mode = 'dropdown'
style = {{width: '80%', marginLeft: 30}}
selectedValue={this.state.pickerFloorID}
onValueChange={(itemValue, itemIndex) => {
this.setState({pickerFloorID:itemValue})
}}
>
<Picker.Item label = {defaultPlaceholder} value = {defaultPlaceholder} />
{pickerFloorsList}
</Picker>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30}}> Suite </Text>
<Picker
mode = 'dropdown'
style = {{width: '80%', marginLeft: 30}}
selectedValue={this.state.pickerSuiteID}
onValueChange={(itemValue, itemIndex) => {
this.setState({pickerSuiteID:itemValue})
}}
>
<Picker.Item label = {defaultPlaceholder} value = {defaultPlaceholder} />
{pickerSuitesList}
</Picker>
<TouchableHighlight
style={{ backgroundColor: 'gray', left: 200, width: 165, height: 40, justifyContent: 'center', alignItems: 'center', top: 10}}
activeOpacity = {1}
onPress={() => {
//Go to render map component
}}
>
<Text style = {{color: '#FFFFFF', fontSize: 18}}> Display suite map </Text>
</TouchableHighlight>
</View>
)
答案 0 :(得分:0)
我建议您将选择器项目生成器置于render方法之外,这样您的代码应类似于以下内容:
(我尝试了这部分代码,看起来工作正常,但我没有实现您的逻辑)
import React from 'react';
import {
View,
Text,
Picker,
TouchableHighlight,
ScrollView,
} from 'react-native';
const defaultPlaceholder = 'default placeholder';
const uniqueFacilityIDs = [
{
key: 'facility_key_1',
facilityName: 'Facility Name 1',
facilityID: 'facility_id_1'
},
{
key: 'facility_key_2',
facilityName: 'Facility Name 2',
facilityID: 'facility_id_2'
},
];
const uniqueFloorIDs = [
{
key: 'floor_key_1',
floorName: 'Floor Name 1',
floorID: 'floor_id_1'
},
{
key: 'floor_key_2',
floorName: 'Floor Name 2',
floorID: 'floor_id_2'
},
];
const uniqueSuiteIDs = [
{
key: 'suits_key_1',
suiteName: 'Suits Name 1',
suiteID: 'suits_id_1'
},
{
key: 'suits_key_2',
suiteName: 'Suits Name 2',
suiteID: 'suits_id_2'
},
];
class App extends React.Component {
state = {
pickerFacilityID: defaultPlaceholder,
pickerFloorID: defaultPlaceholder,
pickerSuiteID: defaultPlaceholder,
};
renderFacilitiesPickerItems = () => uniqueFacilityIDs.map(a => {
return <Picker.Item key={a.key} label={a.facilityName} value={a.facilityID}/>;
});
renderFloorsPickerItems = () => uniqueFloorIDs.map(a => {
return <Picker.Item key={a.key} label={a.floorName} value={a.floorID}/>;
});
renderSuitesPickerItems = () => uniqueSuiteIDs.map(a => {
return <Picker.Item key={a.key} label={a.suiteName} value={a.suiteID}/>;
});
render() {
if (this.state.pickerFacilityID === defaultPlaceholder || this.state.pickerFloorID === defaultPlaceholder || this.state.pickerSuiteID === defaultPlaceholder) {
return (
<ScrollView>
<View>
<Text style={{
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
marginBottom: 25,
marginTop: 15
}}> Display Assets by Suites </Text>
<Text style={{
fontSize: 16.5,
textAlign: 'left',
marginLeft: 30,
marginBottom: 15,
textDecorationLine: 'underline'
}}>Filter suites by:</Text>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30}}> Facility </Text>
<Picker
mode='dropdown'
style={{width: '80%', marginLeft: 30}}
selectedValue={this.state.pickerFacilityID}
onValueChange={(itemValue, _itemIndex) => {
this.setState({pickerFacilityID: itemValue})
}}
>
<Picker.Item label={defaultPlaceholder} value={defaultPlaceholder}/>
{this.renderFacilitiesPickerItems()}
</Picker>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30}}> Floor </Text>
<Picker
mode='dropdown'
style={{width: '80%', marginLeft: 30}}
selectedValue={this.state.pickerFloorID}
onValueChange={(itemValue, itemIndex) => {
this.setState({pickerFloorID: itemValue})
}}
>
<Picker.Item label={defaultPlaceholder} value={defaultPlaceholder}/>
{this.renderFloorsPickerItems()}
</Picker>
<Text style={{fontSize: 16.5, textAlign: 'left', marginLeft: 30}}> Suite </Text>
<Picker
mode='dropdown'
style={{width: '80%', marginLeft: 30}}
selectedValue={this.state.pickerSuiteID}
onValueChange={(itemValue, itemIndex) => {
this.setState({pickerSuiteID: itemValue})
}}
>
<Picker.Item label={defaultPlaceholder} value={defaultPlaceholder}/>
{this.renderSuitesPickerItems()}
</Picker>
</View>
</ScrollView>
)
} else {
return (
<TouchableHighlight
style={{
backgroundColor: 'gray',
left: 200,
width: 165,
height: 40,
justifyContent: 'center',
alignItems: 'center',
top: 10
}}
activeOpacity={1}
onPress={() => {
//Go to render map component
}}
>
<Text style={{color: '#FFFFFF', fontSize: 18}}> Display suite map </Text>
</TouchableHighlight>
)
}
}
}
export default App;