blog bg

June 05, 2024

Building a Goals App with React Native: Core Concepts and Styling

Share what you learn in this blog to prepare for your interview, create your forever-free profile now, and explore how to monetize your valuable knowledge.

Building a Goals App with React Native: Core Concepts and Styling

 

Introduction

In this post, we are going to dive into React Native core concepts, explore its components, build user interfaces, and learn how to style these components. We will also add interactivity to our project by implementing state management with React. Our project will be a simple goals application.

To get started, please follow up on my previous post .

 

Introducing the App.tsx File

In the App.tsx file, we have a functional component similar to a web React component, but instead of HTML elements like <div> and <p>, we use React Native components. React Native does not use CSS; instead, it uses a class object called StyleSheet from the React Native package. This object has a create method that accepts key-value pairs, similar to CSS inline styling, and returns an object with these styles. It is good practice to define component styling within the component itself, as shown below:

 


const styles = StyleSheet.create({
 container: {
   flex: 1,
   backgroundColor: '#fff',
   alignItems: 'center',
   justifyContent: 'center',
 },
});

 

In our functional component App, we can use the style as follows:

 


import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
 return (
   <View style={styles.container}>
     <Text>Hello world</Text>
     <StatusBar style="auto" />
   </View>
 );
}
const styles = StyleSheet.create({
 container: {
   flex: 1,
   backgroundColor: '#fff',
   alignItems: 'center',
   justifyContent: 'center',
 },
});
```

 

Text and View are two of the most important built-in components in React Native for building user interfaces. You can think of them as the <p> and <div> tags in web development, respectively. They are both imported from the react-native package.

 

Find the list of React Native components in the docs: React Native Components.

 

Styling in React Native

Styling can be done in two ways: inline styling by using props on the core components or using the StyleSheet objects. Styles are written in JavaScript, with many properties inspired by CSS, though not all property names are the same.

 

Example using inline styling:


import { StyleSheet, Text, View, Button } from 'react-native';
export default function App() {
 return (
   <View style={styles.container}>
     <View>
       <Text>Another Text</Text>
     </View>
     <Text style={{ margin: 16, borderWidth: 2, borderColor: 'red', padding: 16 }}>
       This is how Texts are rendered
     </Text>
     <Button title="button" />
   </View>
 );
}
const styles = StyleSheet.create({
 container: {
   flex: 1,
   backgroundColor: '#fff',
   alignItems: 'center',
   justifyContent: 'center',
 },
});

 

Example using StyleSheet objects:

 

import { StyleSheet, Text, View, Button } from 'react-native';
export default function App() {
 return (
   <View style={styles.container}>
     <View>
       <Text style={styles.textContainer}>Another Text</Text>
     </View>
     <Text style={styles.inlineText}>
       This is how Texts are rendered
     </Text>
     <Button title="button" />
   </View>
 );
}
const styles = StyleSheet.create({
 container: {
   flex: 1,
   backgroundColor: '#fff',
   alignItems: 'center',
   justifyContent: 'center',
 },
 textContainer: {
   margin: 16,
   padding: 2,
   borderWidth: 2,
   borderColor: 'blue',
 },
 inlineText: {
   margin: 16,
   borderWidth: 2,
   borderColor: 'red',
   padding: 16,
 },
});
```

 

Working with Layouts

In React Native, layouts are created using Flexbox. Unlike in web development, Flexbox is added to the View component by default, and the default direction is column.

 

import { StyleSheet, Text, View, Button, TextInput } from 'react-native';
export default function App() {
 return (
   <View style={styles.appContainer}>
     <View style={styles.inputContainer}>
       <TextInput style={styles.textInput} placeholder="Your course goal!" />
       <Button title="Add Goal" />
     </View>
     <View style={styles.goalsContainer}>
       <Text>List of goals...</Text>
     </View>
   </View>
 );
}
const styles = StyleSheet.create({
 appContainer: {
   paddingTop: 50,
   paddingHorizontal: 16,
   flex: 1,
 },
 inputContainer: {
   flex: 1,
   flexDirection: 'row',
   justifyContent: 'space-between',
   alignItems: 'center',
   marginBottom: 24,
   borderBottomWidth: 1,
   borderBottomColor: '#cccccc',
 },
 textInput: {
   borderWidth: 1,
   borderColor: '#cccccc',
   width: '70%',
   marginRight: 8,
   padding: 8,
 },
 goalsContainer: {
   flex: 5,
 },
});

 

Handling Events

Interactivity is crucial in most apps. We handle events using event listeners, similar to web React apps. We will handle two events: a click on the "Add Goal" button and keystrokes on the text input element to capture user input.

 

import { useState } from 'react';
import { StyleSheet, Text, View, Button, TextInput } from 'react-native';
export default function App() {
 const [goalText, setGoalText] = useState('');
 function goalInputHandler(text: string) {
   console.log(text);
   setGoalText(text);
 }
 function addGoalHandler() {
   console.log('Button clicked:', goalText);
 }
 return (
   <View style={styles.appContainer}>
     <View style={styles.inputContainer}>
       <TextInput
         style={styles.textInput}
         placeholder="Your course goal!"
         onChangeText={goalInputHandler}
       />
       <Button title="Add Goal" onPress={addGoalHandler} />
     </View>
     <View style={styles.goalsContainer}>
       <Text>List of goals...</Text>
     </View>
   </View>
 );
}
const styles = StyleSheet.create({
 appContainer: {
   paddingTop: 50,
   paddingHorizontal: 16,
   flex: 1,
 },
 inputContainer: {
   flex: 1,
   flexDirection: 'row',
   justifyContent: 'space-between',
   alignItems: 'center',
   marginBottom: 24,
   borderBottomWidth: 1,
   borderBottomColor: '#cccccc',
 },
 textInput: {
   borderWidth: 1,
   borderColor: '#cccccc',
   width: '70%',
   marginRight: 8,
   padding: 8,
 },
 goalsContainer: {
   flex: 5,
 },
});

 

Managing the Goals List

We will use state to manage our goals list, as it needs to be updated frequently on the UI.

 


import { useState } from 'react';
import { StyleSheet, Text, View, Button, TextInput } from 'react-native';
export default function App() {
 const [goalText, setGoalText] = useState('');
 const [goals, setGoals] = useState<string[]>([]);
 function goalInputHandler(text: string) {
   setGoalText(text);
 }
 function addGoalHandler() {
   setGoals((prevGoals) => [...prevGoals, goalText]);
 }
 return (
   <View style={styles.appContainer}>
     <View style={styles.inputContainer}>
       <TextInput
         style={styles.textInput}
         placeholder="Your course goal!"
         onChangeText={goalInputHandler}
       />
       <Button title="Add Goal" onPress={addGoalHandler} />
     </View>
     <View style={styles.goalsContainer}>
       {goals.map((goal, index) => (
         <View key={index} style={styles.goalItem}>
           <Text style={styles.goalText}>{goal}</Text>
         </View>
       ))}
     </View>
   </View>
 );
}
const styles = StyleSheet.create({
 appContainer: {
   paddingTop: 50,
   paddingHorizontal: 16,
   flex: 1,
 },
 inputContainer: {
   flex: 1,
   flexDirection: 'row',
   justifyContent: 'space-between',
   alignItems: 'center',
   marginBottom: 24,
   borderBottomWidth: 1,
   borderBottomColor: '#cccccc',
 },
 textInput: {
   borderWidth: 1,
   borderColor: '#cccccc',
   width: '70%',
   marginRight: 8,
   padding: 8,
 },
 goalsContainer: {
   flex: 5,
 },
 goalItem: {
   margin: 8,
   padding: 8,
   borderRadius: 6,
   backgroundColor: '#5e0acc',
 },
 goalText: {
   color: 'white',
 },
});

Here, we keep our goals in an array called goals, and when we add a goal, we append it to this array. For each goal in the list, we render a Text component wrapped inside a View to style it. React Native requires a key prop for each element in a list to efficiently manage re-renders.

 

Conclusion

We have successfully built a simple goals application using React Native. We covered core concepts like components, state management, styling, and handling events. This is just the beginning; you can further enhance this application by adding more features, such as editing or deleting goals, persisting data, and more.
 

Stay tuned for more advanced topics in React Native in upcoming posts!


Github Repo: https://github.com/Intuneteq/react-native-tutorials/tree/tutorial-two

React Native Doc: https://docs.expo.dev/

874 views

Please Login to create a Question