Picker状态在React native中不起作用

时间:2018-03-12 06:21:06

标签: javascript react-native

我通过点击按钮动态地将Pickers添加到反应原生注册表单中。 UI看起来像这个截图。

enter image description here

如果我按“添加语言”,则会出现另一行,用户可以注册另一对语言进行翻译。

我的问题是如何才能改变选项。现在,当我更改选项时它会崩溃。我的代码:

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>
        );
    }
}

1 个答案:

答案 0 :(得分:-1)

尝试通过concat而不是push来改变状态。 我怀疑在以下方法中发生了某种突变错误。

   handleChangeOption(val) {
            //this.state.itemValues.push(val);
            this.state.itemValues.concat(val);
            //if (val !== 0) {
             //   this.setState({itemValues: itemValues});
           // }
        }