0
0
React Nativemobile~20 mins

Lifting state up in React Native - Mini App: Build & Ship

Choose your learning style9 modes available
Build: Temperature Converter
A screen that converts temperature between Celsius and Fahrenheit. The user can enter a value in either input, and the other input updates automatically.
Target UI
-------------------------
| Temperature Converter  |
|-----------------------|
| Celsius: [        ]    |
| Fahrenheit: [        ] |
|                       |
| (Both inputs update each|
|  other when changed)   |
-------------------------
Two text inputs labeled 'Celsius' and 'Fahrenheit'.
Typing a number in Celsius updates Fahrenheit automatically.
Typing a number in Fahrenheit updates Celsius automatically.
State should be lifted up to a common parent to keep inputs in sync.
Inputs accept only numeric values.
Starter Code
React Native
import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';

export default function TemperatureConverter() {
  // TODO: Add state here

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Celsius:</Text>
      <TextInput
        style={styles.input}
        keyboardType="numeric"
        // TODO: Add value and onChangeText for Celsius
      />

      <Text style={styles.label}>Fahrenheit:</Text>
      <TextInput
        style={styles.input}
        keyboardType="numeric"
        // TODO: Add value and onChangeText for Fahrenheit
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  label: {
    fontSize: 18,
    marginTop: 20,
  },
  input: {
    borderWidth: 1,
    borderColor: '#999',
    padding: 8,
    fontSize: 18,
    borderRadius: 4,
  },
});
Task 1
Task 2
Task 3
Task 4
Solution
React Native
import React, { useState } from 'react';
import { View, Text, TextInput, StyleSheet } from 'react-native';

function toCelsius(fahrenheit) {
  return ((fahrenheit - 32) * 5) / 9;
}

function toFahrenheit(celsius) {
  return (celsius * 9) / 5 + 32;
}

function tryConvert(temperature, convert) {
  const input = parseFloat(temperature);
  if (Number.isNaN(input)) {
    return '';
  }
  const output = convert(input);
  const rounded = Math.round(output * 1000) / 1000;
  return rounded.toString();
}

export default function TemperatureConverter() {
  const [temperature, setTemperature] = useState('');
  const [scale, setScale] = useState('c');

  const handleCelsiusChange = (text) => {
    setTemperature(text);
    setScale('c');
  };

  const handleFahrenheitChange = (text) => {
    setTemperature(text);
    setScale('f');
  };

  const celsius = scale === 'f' ? tryConvert(temperature, toCelsius) : temperature;
  const fahrenheit = scale === 'c' ? tryConvert(temperature, toFahrenheit) : temperature;

  return (
    <View style={styles.container}>
      <Text style={styles.label}>Celsius:</Text>
      <TextInput
        style={styles.input}
        keyboardType="numeric"
        value={celsius}
        onChangeText={handleCelsiusChange}
        accessibilityLabel="Celsius input"
      />

      <Text style={styles.label}>Fahrenheit:</Text>
      <TextInput
        style={styles.input}
        keyboardType="numeric"
        value={fahrenheit}
        onChangeText={handleFahrenheitChange}
        accessibilityLabel="Fahrenheit input"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  label: {
    fontSize: 18,
    marginTop: 20,
  },
  input: {
    borderWidth: 1,
    borderColor: '#999',
    padding: 8,
    fontSize: 18,
    borderRadius: 4,
  },
});

We keep the temperature value and the scale (which input was last changed) in the parent component's state. When the user types in one input, we update the temperature and scale. Then we convert the temperature to the other scale for the other input. This way, both inputs stay in sync.

We use helper functions to convert between Celsius and Fahrenheit. The inputs accept only numeric values and show the converted temperature rounded to three decimals.

This pattern is called "lifting state up" because the shared state lives in the common parent, not inside each input separately.

Final Result
Completed Screen
-------------------------
| Temperature Converter  |
|-----------------------|
| Celsius: [  25.0   ]   |
| Fahrenheit: [ 77.0  ]  |
|                       |
| (Typing in one input   |
|  updates the other)    |
-------------------------
Typing a number in the Celsius input updates the Fahrenheit input automatically.
Typing a number in the Fahrenheit input updates the Celsius input automatically.
Only numeric input is accepted in both fields.
Stretch Goal
Add a clear button that resets both inputs to empty.
💡 Hint
Add a Button component below inputs that sets temperature state to empty string and scale to 'c' when pressed.