我通过点击按钮动态地将Pickers添加到反应原生注册表单中。 UI看起来像这个截图。
如果我按“添加语言”,则会出现另一行,用户可以注册另一对语言进行翻译。
我的问题是如何才能改变选项。现在,当我更改选项时它会崩溃。我的代码:
import React from 'react';
import {Image, Picker, StyleSheet, Text, TouchableHighlight, View} from 'react-native';
import {StackNavigator} from 'react-navigation'; // Version can be specified in package.json
import {Constants} from 'expo';
class HomeScreen extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={styles.section1}>
<Text style={[styles.text, {paddingBottom: 20}]}>{'Welcome'}</Text>
</View>
<View style={styles.section2}>
<Text style={[styles.text, {paddingTop: 20}]}>{'Your verification was successful'}</Text>
</View>
<View style={styles.section3}>
<Text style={styles.text}>{'Sign up as:'}</Text>
</View>
<View style={styles.section4}>
<View style={styles.buttonContainer}>
<View style={styles.button}>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Details')}>
<Image source={require('./assets/stck2.png')} style={styles.image}/>
</TouchableHighlight>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Details')}>
<Text style={styles.buttonText}>{'Translator'}</Text>
</TouchableHighlight>
</View>
<View style={styles.button}>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Recruiter')}>
<Image source={require('./assets/stck1.png')} style={styles.image}/>
</TouchableHighlight>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Recruiter')}>
<Text style={styles.buttonText}>{'Recruiter'}</Text>
</TouchableHighlight>
</View>
</View>
</View>
</View>
);
}
}
class DetailsScreen extends React.Component {
state = {count : 0, itemValues : [], pickers : [], user: '',
isoLangs : {
"ab":{
"name":"Abkhaz",
"nativeName":"аҧсуа"
},
"aa":{
"name":"Afar",
"nativeName":"Afaraf"
},
"af":{
"name":"Afrikaans",
"nativeName":"Afrikaans"
},
"ak":{
"name":"Akan",
"nativeName":"Akan"
},
"sq":{
"name":"Albanian",
"nativeName":"Shqip"
},
"am":{
"name":"Amharic",
"nativeName":"አማርኛ"
},
"ar":{
"name":"Arabic",
"nativeName":"العربية"
},
"an":{
"name":"Aragonese",
"nativeName":"Aragonés"
},
"hy":{
"name":"Armenian",
"nativeName":"Հայերեն"
},
"as":{
"name":"Assamese",
"nativeName":"অসমীয়া"
},
"av":{
"name":"Avaric",
"nativeName":"авар мацӀ, магӀарул мацӀ"
},
"ae":{
"name":"Avestan",
"nativeName":"avesta"
},
"ay":{
"name":"Aymara",
"nativeName":"aymar aru"
},
"az":{
"name":"Azerbaijani",
"nativeName":"azərbaycan dili"
},
"bm":{
"name":"Bambara",
"nativeName":"bamanankan"
},
"ba":{
"name":"Bashkir",
"nativeName":"башҡорт теле"
},
"eu":{
"name":"Basque",
"nativeName":"euskara, euskera"
},
"be":{
"name":"Belarusian",
"nativeName":"Беларуская"
},
"bn":{
"name":"Bengali",
"nativeName":"বাংলা"
},
"bh":{
"name":"Bihari",
"nativeName":"भोजपुरी"
},
"bi":{
"name":"Bislama",
"nativeName":"Bislama"
},
"bs":{
"name":"Bosnian",
"nativeName":"bosanski jezik"
},
"br":{
"name":"Breton",
"nativeName":"brezhoneg"
},
"bg":{
"name":"Bulgarian",
"nativeName":"български език"
},
"my":{
"name":"Burmese",
"nativeName":"ဗမာစာ"
},
"ca":{
"name":"Catalan; Valencian",
"nativeName":"Català"
},
"ch":{
"name":"Chamorro",
"nativeName":"Chamoru"
},
"ce":{
"name":"Chechen",
"nativeName":"нохчийн мотт"
},
"ny":{
"name":"Chichewa; Chewa; Nyanja",
"nativeName":"chiCheŵa, chinyanja"
},
"zh":{
"name":"Chinese",
"nativeName":"中文 (Zhōngwén), 汉语, 漢語"
},
"cv":{
"name":"Chuvash",
"nativeName":"чӑваш чӗлхи"
},
"kw":{
"name":"Cornish",
"nativeName":"Kernewek"
},
"co":{
"name":"Corsican",
"nativeName":"corsu, lingua corsa"
},
"cr":{
"name":"Cree",
"nativeName":"ᓀᐦᐃᔭᐍᐏᐣ"
}
}};
getLanguageName = function(key) {
key = key.slice(0,2);
lang = this.state.isoLangs[key];
return lang ? lang.name : undefined;
};
getLanguageNativeName = function(key) {
key = key.slice(0,2);
lang = this.state.isoLangs[key];
return lang ? lang.nativeName : undefined;
};
handleChangeOption(val) {
this.state.itemValues.push(val);
//if (val !== 0) {
// this.setState({itemValues: itemValues});
// }
}
addLanguage(){
pickers = this.state.pickers;
this.state.count++;
pickers.push( <View key={Math.random()} style={{flexDirection: 'row', justifyContent: 'center'}}>
<Picker style={{width: 150}}
selectedValue={this.state.itemValues[this.state.count]}
onValueChange={this.handleChangeOption}>
{
Object.keys(this.state.isoLangs).map((lang) => {
return <Picker.Item key={lang} label={this.state.isoLangs[lang].name} value={lang} />
})
}
</Picker>
<Image
source={require('./assets/Arrow.png')}
/>
<Picker style={{width: 150}}
selectedValue={this.state.language}
onValueChange={(itemValue) => this.setState({language: itemValue})}>
{
Object.keys(this.state.isoLangs).map((lang) => {
return <Picker.Item key={lang} label={this.state.isoLangs[lang].name} value={lang} />
})
}
</Picker>
</View>);
this.setState({
...this.state,
pickers:pickers
});
}
render() {
console.log('render: ');
keys = Array.from( this.state.isoLangs );
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<View style={{flexDirection: 'row', justifyContent: 'center'}}>
<Text style={{
fontSize: 20,
fontFamily: 'normal',
color: 'skyblue',
}}>
Which languages do you translate?
</Text>
</View>
{this.state.pickers.map((picker)=>{console.log('picker: ', picker);return picker})}
<TouchableHighlight onPress={() => this.addLanguage()}>
<Text style={{
fontSize: 20,
fontFamily: 'normal',
color: 'skyblue',
}}>+ add language</Text>
</TouchableHighlight>
<View style={{flexDirection: 'row', justifyContent: 'center'}}>
<TouchableHighlight onPress={() => this.props.navigation.navigate('Screen3')}>
<Image
source={require('./assets/Next.png')}
/>
</TouchableHighlight>
</View>
</View>
);
}
}
const RootStack = StackNavigator(
{
Home: {
screen: HomeScreen,
},
Details: {
screen: DetailsScreen,
},
},
{
initialRouteName: 'Home',
}
);
export default class App extends React.Component {
render() {
return <RootStack/>;
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: Constants.statusBarHeight,
backgroundColor: '#fff',
},
section1: {
flex: 0.17,
justifyContent: 'flex-end',
alignItems: 'center'
},
section2: {
flex: 0.30,
justifyContent: 'flex-start',
alignItems: 'center'
},
section3: {
flex: 0.10,
justifyContent: 'center',
alignItems: 'center'
},
section4: {
flex: 0.43
},
text: {
fontSize: 24,
color: '#53a6db',
textAlign: 'center',
paddingTop: 40,
paddingBottom: 40,
paddingLeft: 40,
paddingRight: 40
},
buttonContainer: {
flex: 1,
flexDirection: 'row'
},
button: {
flex: 0.5,
justifyContent: 'center',
alignItems: 'center'
},
buttonText: {
fontSize: 24,
color: '#53a6db',
textAlign: 'center',
paddingTop: 5,
paddingBottom: 5,
paddingLeft: 5,
paddingRight: 5
},
image: {
width: 100,
height: 100
}
});
解决方案
import React from 'react';
import {Picker, Text, TouchableHighlight, View} from 'react-native';
export default class DetailsScreen extends React.Component {
constructor(props) {
super(props);
// this.state = { itemValue: this.prop.initialSelectedValue };
// this.handleChangeOption = this.handleChangeOption.bind(this);
this.addLanguage = this.addLanguage.bind(this)
// this.update = this.update.bind(this)
}
state = {
count: 0, itemValues: [], languages : [], pickers: [], user: '',
someVal: 'ar',
isoLangs: {
"ab": {
"name": "Abkhaz",
"nativeName": "аҧсуа"
},
"aa": {
"name": "Afar",
"nativeName": "Afaraf"
},
"af": {
"name": "Afrikaans",
"nativeName": "Afrikaans"
},
"ak": {
"name": "Akan",
"nativeName": "Akan"
},
"sq": {
"name": "Albanian",
"nativeName": "Shqip"
},
"am": {
"name": "Amharic",
"nativeName": "አማርኛ"
},
"ar": {
"name": "Arabic",
"nativeName": "العربية"
}
}
};
update() {
console.log('update ' + this.state.itemValues);
return this.state.itemValues[0] || 'ar';
}
onNewValueSelected = (newVal) => {
console.log('You selected the value: ' + newVal)
// this.setState({someVal: newVal});
//pickers = this.state.pickers;
this.setState({
...this.state,
someVal: newVal
// itemValues:itemValues
// pickerValue: pickerValue
});
}
addLanguage() {
console.log('addLanguage');
let pickers = this.state.pickers;
// this.state.itemValues[0] = 'fr';
count = this.state.count;
count++;
pickers.push(
{
id: 1,
color: "blue",
text: "text1"
}
);
languages = this.state.languages;
languages.push('new');
this.setState({
// ...this.state,
// pickers: pickers,
count: count,
languages: languages,
// itemValues:itemValues
// pickerValue: pickerValue
});
}
update(lang, ran, counter){
languages = this.state.languages;
languages[counter]=lang;
// if (languages[0])
// languages.pop();
// languages.push(lang);
this.setState({
languages: languages,
// itemValues:itemValues
});
}
render() {
console.log('render someVal: ' + this.state.someVal);
counter = 0;
return (
<View style={{flex: 1, justifyContent: 'center'}}>
<View style={{flexDirection: 'row', justifyContent: 'center'}}>
<Text style={{
fontSize: 20,
fontFamily: 'normal',
color: 'skyblue',
}}>
Which languages do you translate?
</Text>
</View>
<View key={Math.random()} style={{flexDirection: 'row', justifyContent: 'center'}}>
<Picker key={Math.random()} style={{width: 150}}
selectedValue={this.state.language}
onValueChange={(lang) => this.setState({language: lang})}
>
{
Object.keys(this.state.isoLangs).map((lang) => {
return <Picker.Item key={lang} label={this.state.isoLangs[lang].name} value={lang}/>
})
}
</Picker>
</View>
{this.state.pickers.map((picker) => {
let ran = Math.random();
counter++;
return <View key={Math.random()} style={{flexDirection: 'row', justifyContent: 'center'}}>
<Picker key={ran} style={{width: 150}} selectedValue={this.state.languages[counter-1]}
onValueChange={(lang) => this.update(lang, ran, counter-1)}
>
{
Object.keys(this.state.isoLangs).map((lang) => {
return <Picker.Item key={Math.random()} label={this.state.isoLangs[lang].name} value={lang}/>
})
}
</Picker></View>
})}
<TouchableHighlight onPress={() => this.addLanguage()}>
<Text style={{
fontSize: 20,
fontFamily: 'normal',
color: 'skyblue',
}}>+ add language</Text>
</TouchableHighlight>
</View>
);
}
}
答案 0 :(得分:-1)
尝试通过concat而不是push来改变状态。 我怀疑在以下方法中发生了某种突变错误。
handleChangeOption(val) {
//this.state.itemValues.push(val);
this.state.itemValues.concat(val);
//if (val !== 0) {
// this.setState({itemValues: itemValues});
// }
}