简体   繁体   中英

How to store a value in a state in React Native?

I've created a small form with two options. Basically I want the user to choose one option and to pass that value in the state "preference" (and further to pass that value in firebase). I'm not sure if my approach with the "If Condition" to choose between options is the correct way because I am a Javascript and React Native beginner.

How would you approach this in terms of code?

 export default class ChooseOption extends Component {

    state = {
        option1: false,
        option2: false,
        preference: ''
    }

    chooseFirst = () => {
        if (this.state.option1 == false) {
            this.setState({ option1: true})
            this.setState({ option2: false })
        }
    }

    chooseSecond = () => {
        if (this.state.option2 == false) {
            this.setState({option2: true})
            this.setState({option1: false})
        }
    }

    render() {

        return(

            <View style={styles.container}>

                <Text style={styles.greeting}>Select one option:</Text>

                <View style={styles.form}>

                    <TouchableOpacity 
                        onPress={this.chooseFirst}
                        style={{flexDirection:'row', alignItems: 'center'}}>
                        <Icon 
                            name={this.state.option1 ? 'md-radio-button-on' : 'md-radio-button-off'}
                            size={30} 
                            color= {this.state.option1 ? 'green' : 'gray'}
                        />
                        <Text 
                            style={this.state.option1 ? styles.textOn : styles.textOff}>First Option</Text>
                    </TouchableOpacity>

                    <TouchableOpacity 
                        onPress={this.chooseSecond}
                        style={{marginTop: 30, flexDirection:'row', alignItems: 'center'}}>
                        <Icon 
                            name={this.state.option2 ? 'md-radio-button-on' : 'md-radio-button-off'}
                            size={30} 
                            color= {this.state.option2 ? 'green' : 'gray'}
                            />
                        <Text 
                            style={this.state.option2 ? styles.textOn : styles.textOff}>Second Option</Text>
                    </TouchableOpacity>

                </View> 
        </View>
       );
    }
}

const styles = StyleSheet.create({
container: {
    flex: 1,
},
greeting: {
    marginHorizontal: 30,
    marginTop: 307,
    fontSize: 30,
    lineHeight: 40,
},
form: {
    marginTop: 39,
    marginBottom: 115,
    marginHorizontal: 30
},
textOff: {
    color: 'gray',
    fontSize: 28,
    textTransform: 'none',
    letterSpacing: 2,
    left: 10
},
textOn: {
    color: 'green',
    fontSize: 28,
    textTransform: 'none',
    letterSpacing: 2,
    left: 10
},
})

If you want to use booleans to keep track of selected option then I would go with one variable, because in case of radio buttons only one at a time can be selected so second boolean is redundant. Here is one example of doing it:

export default class ChooseOption extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isOption1Selected: true,
      preference: '',
    };
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.greeting}>Select one option:</Text>
        <View style={styles.form}>
          <TouchableOpacity
            onPress={() => this.setState({ isOption1Selected: true })}
            style={{ flexDirection: 'row', alignItems: 'center' }}>
            <View
              name={this.state.isOption1Selected ? 'md-radio-button-on' : 'md-radio-button-off'}
              size={30}
              color={this.state.isOption1Selected ? 'green' : 'gray'}
            />
            <Text
              style={this.state.isOption1Selected ? styles.textOn : styles.textOff}>First Option</Text>
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => this.setState({ isOption1Selected: false })}
            style={{ marginTop: 30, flexDirection: 'row', alignItems: 'center' }}>
            <View
              name={!this.state.isOption1Selected ? 'md-radio-button-on' : 'md-radio-button-off'}
              size={30}
              color={!this.state.isOption1Selected ? 'green' : 'gray'}
            />
            <Text
              style={!this.state.isOption1Selected ? styles.textOn : styles.textOff}>Second Option</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

But imagine if you have to add more options then it would be better to keep track of an id of selected option which you could implement in this way:

export default class ChooseOption extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedOptionId: 0,
      preference: '',
    };
  }

  render() {
    const { selectedOptionId } = this.state;
    return (
      <View style={styles.container}>
        <Text style={styles.greeting}>Select one option:</Text>
        <View style={styles.form}>
          <TouchableOpacity
            onPress={() => this.setState({ selectedOptionId: 0, preference: 'First option' })}
            style={{ flexDirection: 'row', alignItems: 'center' }}>
            <View
              name={selectedOptionId === 0 ? 'md-radio-button-on' : 'md-radio-button-off'}
              size={30}
              color={selectedOptionId === 0 ? 'green' : 'gray'}
            />
            <Text
              style={selectedOptionId === 0 ? styles.textOn : styles.textOff}>First Option</Text>
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => this.setState({ selectedOptionId: 1, preference: 'Second option' })}
            style={{ marginTop: 30, flexDirection: 'row', alignItems: 'center' }}>
            <View
              name={selectedOptionId === 1 ? 'md-radio-button-on' : 'md-radio-button-off'}
              size={30}
              color={selectedOptionId === 1 ? 'green' : 'gray'}
            />
            <Text
              style={selectedOptionId === 1 ? styles.textOn : styles.textOff}>Second Option</Text>
          </TouchableOpacity>
          <TouchableOpacity
            onPress={() => this.setState({ selectedOptionId: 2, preference: 'Third option' })}
            style={{ marginTop: 30, flexDirection: 'row', alignItems: 'center' }}>
            <View
              name={selectedOptionId === 2 ? 'md-radio-button-on' : 'md-radio-button-off'}
              size={30}
              color={selectedOptionId === 2 ? 'green' : 'gray'}
            />
            <Text
              style={selectedOptionId === 2 ? styles.textOn : styles.textOff}>Third Option</Text>
          </TouchableOpacity>
        </View>
      </View>
    );
  }
}

And finally you could write a function to generate all the options from predefined array so that your code stays clean:

const options = [
  { id: 0, text: 'First option'},
  { id: 1, text: 'Second option'},
  { id: 2, text: 'Third option'},
]

export default class ChooseOption extends Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedOptionId: 0,
      preference: '',
    };
  }

  createOption(optionData) {
    const { selectedOptionId } = this.state;
    const { id, text } = optionData;
    return (
      <TouchableOpacity
        key={id}
        onPress={() => this.setState({ selectedOptionId: id, preference: text })}
        style={{ flexDirection: 'row', alignItems: 'center' }}>
        <View
          name={selectedOptionId === id ? 'md-radio-button-on' : 'md-radio-button-off'}
          size={30}
          color={selectedOptionId === id ? 'green' : 'gray'}
        />
        <Text
          style={selectedOptionId === id ? styles.textOn : styles.textOff}>{text}</Text>
      </TouchableOpacity>
    );
  }

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.greeting}>Select one option:</Text>
        <View style={styles.form}>
          {
            options.map((op) => this.createOption(op))
          }
        </View>
      </View>
    );
  }
}

UPDATE

If you want to print preference in console when it is selected, you can do something similar to what you did first time by calling custom function in TouchableOpacity but in a bit different way: onPress={() => this.select(id, text)} . And then define this function like:

select(id, text) {
  this.setState({ selectedOptionId: id, preference: text });
  console.log(text);
}

Option for what? Lets assume its for theme: option1 (dark) and option2 (light)

Lets say its option for themes

  const THEMES = {
    DARK: "dark",
    LIGHT: "light"
  };

  state = {
    selectedTheme : undefined,
    preference: ''
  }

  chooseFirst = () => {     
    this.setState({ selectedTheme:THEMES.DARK })    
  }

  chooseSecond = () => {
    this.setState({ selectedTheme:THEMES.LIGHT  })
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM