简体   繁体   中英

setState is not updating for TextInput using hooks in React Native

I have created a program which takes feet and inches as input and converts them into meters and centimeters. The conversion logic is written in useEffect Hook and the logic is working fine and I'm getting the correct answer in console, but the meters is not being displayed on the screen. When I type input I'm only getting output in centimeters but not in meters. Meters is textInput is always blank. Please help!

import React, {useState, useEffect} from 'react';
import {
  View,
  StyleSheet,
  StatusBar,
  Dimensions,
  Image,
  Text,
  TextInput,
} from 'react-native';

import colors from '../constants/colors';
import {Button} from '../components/Button';

const screen = Dimensions.get('window');

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.blue,
  },
  content: {
    paddingTop: screen.height * 0.1,
  },
  logoContainer: {
    alignItems: 'center',
    justifyContent: 'center',
    marginBottom: 20,
  },
  logoBackground: {
    width: screen.width / 0.45,
    height: screen.width * 0.45,
  },
  logo: {
    position: 'absolute',
    width: screen.width * 0.25,
    height: screen.width * 0.25,
  },
  textHeader: {
    color: colors.white,
    fontWeight: 'bold',
    fontSize: 30,
    textAlign: 'center',
    marginBottom: 20,
  },
  text: {
    fontSize: 14,
    color: colors.white,
    textAlign: 'center',
  },
  inputContainer: {
    flexDirection: 'row',
    flex: 1,
    marginBottom: 10,
  },
  header: {
    alignItems: 'flex-end',
    marginHorizontal: 20,
  },
  sideHeading: {
    textAlign: 'center',
    width: screen.width / 5,
    marginTop: 20,
  },
  textBox: {
    textAlign: 'center',
    width: screen.width / 5,
  },
  button: {
    flexDirection: 'row',
    alignItems: 'center',
    flex: 1,
    justifyContent: 'center',
    marginVertical: 20,
    backgroundColor: colors.red,
    width: screen.width / 2,
    marginLeft: screen.width / 3.2,
  },
  buttonText: {
    alignItems: 'center',
    justifyContent: 'center',
    fontSize: 16,
    color: colors.white,
  },
});

export default ({route = {}}) => {
  const params = route.params || {};
  const {
    title,
    baseDefaultFirst,
    baseDefaultSecond,
    quoteDefaultFirst,
    quoteDefaultSecond,
  } = params;

  const [baseValueOne, setBaseValueOne] = useState(baseDefaultFirst);
  const [baseValueTwo, setBaseValueTwo] = useState(baseDefaultSecond);
  const [quoteValueOne, setQuoteValueOne] = useState(quoteDefaultFirst);
  const [quoteValueTwo, setQuoteValueTwo] = useState(quoteDefaultSecond);
  const [firstValue, setFirstValue] = useState(0);
  const [secondValue, setSecondValue] = useState(0);
  const [thirdValue, setThirdValue] = useState(0);
  const [fourthValue, setFourthValue] = useState(0);

  const swapCurrencies = () => {
    setBaseValueOne(quoteValueOne);
    setBaseValueTwo(quoteValueTwo);
    setQuoteValueOne(baseValueOne);
    setQuoteValueTwo(baseValueTwo);
    setFirstValue('');
    setSecondValue('');
    setThirdValue('');
    setFourthValue('');
  };

  useEffect(() => {
    if (baseValueOne === 'FT') {
      const f = parseFloat(firstValue);
      const i = parseFloat(secondValue);
      let finalAnsInCm = parseFloat((12 * f + i) * 2.54);
      const meters = parseInt(finalAnsInCm / 100, 10);
      finalAnsInCm = parseFloat(finalAnsInCm % 100).toFixed(2);
      if (meters != 0 || finalAnsInCm != 0) {
        setThirdValue(meters);
        setFourthValue(finalAnsInCm);
        console.log(meters);
        console.log(finalAnsInCm);
      }
    }
  }, [firstValue, secondValue]);

  return (
    <View style={styles.container}>
      <StatusBar barStyle="light-content" backgroundColor={colors.blue} />
      <View style={styles.content}>
        <View style={styles.logoContainer}>
          <Image
            source={require('../assets/images/background.png')}
            style={styles.logoBackground}
            resizeMode="contain"
          />
          <Image
            source={require('../assets/images/logo.png')}
            style={styles.logo}
            resizeMode="contain"
          />
        </View>
        <Text style={styles.textHeader}>
          {title}
          {' '}
          Converter
        </Text>

        {/* Input */}
        <View style={styles.inputContainer}>
          <Text style={styles.sideHeading}>{baseValueOne}</Text>
          <TextInput
            style={styles.textBox}
            value={firstValue}
            keyboardType="numeric"
            onChangeText={text => setFirstValue(text)}
          />
          <Text style={styles.sideHeading}>{baseValueTwo}</Text>
          <TextInput
            style={styles.textBox}
            value={secondValue}
            keyboardType="numeric"
            onChangeText={text => setSecondValue(text)}
          />
        </View>

        <View style={styles.inputContainer}>
          <Text style={styles.sideHeading}>{quoteValueOne}</Text>
          <TextInput
            editable={false}
            style={styles.textBox}
            value={thirdValue}
            keyboardType="numeric"
          />
          <Text style={styles.sideHeading}>{quoteValueTwo}</Text>
          <TextInput
            editable={false}
            style={styles.textBox}
            value={fourthValue}
            keyboardType="numeric"
          />
        </View>

        <Button text={`Reverse ${title}`} onPress={() => swapCurrencies()} />
      </View>
    </View>
  );
};

Simply add.toString() on both your variable like

    setThirdValue(meters.toString());
    setFourthValue(finalAnsInCm.toString());

It will solve your issue. because TextInput only accepts String value.

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