How I Create Simple Counter App yet Elegant
Tags: reactnative, react, javascript
Published: 2021-03-08 01:23:12

# Introduction

[React Native](https://reactnative.dev) is react framework to build native app (ios or android). To create this project you could either use React Native or Expo [see details](https://reactnative.dev/docs/environment-setup).

# Prerequisite

* React
* Hooks

I assume you already knew basic react and hooks so I am not going to tell you every details. If you pass this, you are good to go to follow this tutorial.

# Let's Start

I am going to use React Native to create a new app.
```
npx react-native init counter
```
You need to run this in terminal. *npx* allows you to create react-native without install react-native globally.

Ok! next, open the project in vs code or any editor that you like. Run project using `yarn start`

Since I used react native command, I need to use simulator or connect my phone in order to see the result [see details](https://reactnative.dev/docs/environment-setup).

In this tutorial, we should focus only at app.js, since we don't have many screens. Delete all code inside it or rewrite it with below code.
```
import React from 'react';
import {View, Text} from 'react-native';

const App = () => {
  return (
    <View>
      <Text>React Native</Text>
    </View>
  );
};

export default App;
```

You should see 'React Native' text in your screen.

Next, we are going to use `useState` to manage our number state. How to do it? Simple, just declare variable to store state. I am going to call it number.
```
const [number, setNumber] = useState(0);
```

`setNumber` here is common way to setState which is combination of 'set' + 'state' variable.

Then, we need to make whole screen to be touchable. To do this, we simply overwrite `View` tag with `TouchableOpacity` from react-native. Don't forget to import that from react-native. Next, pass number state inside `Text` tag. Now your code should be like this
```
<TouchableOpacity>
  <Text>
    {number}
  </Text>
</TouchableOpacity>
```

# Handle State
Now, we need to to handle change of state so then we can increment the number. Pass `onPress` event inside TouchableOpacity tag `<TouchableOpacity onPress={handlePress}>`. Create `handlePress` to `setNumber(number + 1)`.
```
const handlePress = () => {
  setNumber(number + 1);
}
```

You can style number as you wish, to me I just center the number. My code is look like this now.
```
import React, {useState, useEffect} from 'react';
import {
  Text,
  StyleSheet,
  TouchableOpacity
} from 'react-native';

const App = () => {
  const [number, setNumber] = useState(0);

  const handlePress = () => {
    setNumber(number + 1);
  };

  return (
    <TouchableOpacity
      style={styles.container}
      activeOpacity={1}
      onPress={handlePress}>
      <Text style={styles.number}>
        {number}
      </Text>
    </TouchableOpacity>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  number: {
    fontSize: 96,
  }
});

export default App;

```
There is a time when the application doesn't refresh automatically, when this is happen you might just need to stop the app and bundle app again.

# Back Button to Reset State
Since we've done handle state, we need to find a way how to reset state of number to be zero. There are a lot of ways to accomplish this, I will choose back button in smartphone to reset state.

We need to import `Backhandler` from react native. To listen this backhandler we need to use `useEffect`. However, this `Backhandler` only can use in Android device only. You can see details of this [backhandler](https://reactnative.dev/docs/backhandler).

```
useEffect(() => {
  const backAction = () => {
    if (number !== 0) {
      setNumber(0);
      BackHandler.removeEventListener();
    } else {
      BackHandler.exitApp();
    }

    return true;
  };

  const backHandler = BackHandler.addEventListener(
   'hardwareBackPress',
    backAction,
  );

  return () => backHandler.remove();
}, [number]);
```

Whenever back button is pressed, app will check whether number is zero or not. If number is zero then it will exit the app, if number is not zero, then it will reset number to zero. I add `[number]` dependency so this function will run whenever number state changes.

<img width="50%" style="width:50%" src="https://media.giphy.com/media/14sy6VGAd4BdKM/giphy.gif">

Well done, you've completed this main function. However, I will add change theme so this app will look a bit better.

# Switch Theme
We need to import `Switch` from react native. Then add that into your app. You can see details [here](https://reactnative.dev/docs/switch).
```
<Switch
 trackColor={{false: '#767577', true: '#3BBACB'}}
 thumbColor={isEnabled ? '#151A23' : '#F3F4F6'}
 onValueChange={toggleSwitch}
 value={isEnabled}
 style={styles.switch}
/>
```
To track the switch, we use `useState`. Simply `const [isEnabled, setIsEnabled] = useState(false);` and `const toggleSwitch = () => setIsEnabled(!isEnabled);`. We also need to pass background color inside TouchableOpacity. Now our code should be like this.
```
<TouchableOpacity
  style={[
   styles.container,
     {backgroundColor: isEnabled ? '#56CCF2' : '#151A23'},
   ]}
   activeOpacity={1}
   onPress={handlePress}>
   <Text style={[styles.number, {color: isEnabled ? '#151A23' : '#F3F4F6'}]}>
     {number}
   </Text>
   <Switch
      trackColor={{false: '#767577', true: '#3BBACB'}}
      thumbColor={isEnabled ? '#151A23' : '#F3F4F6'}
      onValueChange={toggleSwitch}
      value={isEnabled}
      style={styles.switch}
    />
</TouchableOpacity>

...
switch: {
  position: 'absolute',
  bottom: 0,
  marginBottom: 32,
}
```

Thank you for follow along this tutorial, you can find full code [here](https://github.com/chuluq/counter).