Why Blockchain Is Too Big To Ignore Or Build A Blockchain With JavaScript – Part 2

Prerequisites: Basic knowledge of JavaScript

Outline

  1. Intro
  2. Block class
  3. USDevBlockchain
  4. Mining
  5. Transactions and rewards
  6. Transaction signature

Intro

In the first part of the blog, we have introduced the notion of blockchain and covered the basic concepts. You could dig a lot deeper if you want, but that is the minimum knowledge we need to move on to the next step of the blockchain system of our own. In this part, we will make a blockchain system called USDevCoin. With the help of our system, users will be able to exchange USDev coins and every transaction will be securely stored as blocks in the chain. Now, by no means the system will be secure enough actually to perform the role of a blockchain, but it will be enough to demonstrate the infrastructure. There is a lot to do, so let’s dive right in!

Environment setup

Before getting started, we need to ensure that we have the latest version of Node installed on our machine. Once you confirm it, go ahead and create the main JavaScript file.

We will call the file chain.js and write the first class Block.

Block class

// chain.js
class Block {
	constructor(index, payload, timestamp, previousHash = ""){
		this.index = index;
		this.payload = payload;
		this.timestamp = timestamp;
		this.previousHash = previousHash;
		this.hash = "";
	}
}

The are four arguments given in the constructor of the class Block. They have the following purposes:

index – it will be the index of the block in the chain

payload – data that the block holds. It could be anything. In our case, we will store the number of coins being transferred in this parameter

timestamp – date and time of the record when it was created

previousHash – since we are going to be chaining the blocks, this argument will refer to the hash of the previous block

If you have noticed, we initially set the hash value of the class to an empty string. Now we need a way to calculate the hash value of the block. Hash value entails taking a range of arguments for a digital record, and creating a unique signature. The important thing about this hash is that it always should return the exact same value when we provide identical parameters.
In JavaScript however, the hashing function is not included by default. So we have to use a third-party library called crypto-js.

So we need to run npm install --save crypto-js in our project folder and import the hashing function from the node module. We will specifically use the SHA256 algorithm for hashing.

// chain.js
const  SHA256 = require("crypto-js/sha256");

class Block {
	constructor(index, payload, timestamp, previousHash = ""){
		this.index = index;
		this.payload = payload;
		this.timestamp = timestamp;
		this.previousHash = previousHash;
		this.hash = this.getHashValue;
	}
	getHashValue() {
		return SHA256(
		  this.index + 
		  this.previousHash + 
		  this.timestamp + 
		  JSON.stringify(this.payload)
		).toString();
	}
}

SHA256 algorithm processes the values and returns the hash value as a string. We also need to update the constructor with the new function, so that the hash automatically gets calculated upon creation of a block.

USDevBlockchain class

The next step is to add the USDevBlockchain class.

class USDevBlockchain {
  constructor(){
    // Chain is an array of blocks
    this.chain = [this.getFirstBlock()];
  }

  // We have to create the first block manually
  getFirstBlock() {
    return new Block(0, "First Block (Genesis Block)", new Date(), "0");
  }

  // Returns the latest block in the array
  getLastBlock(){
    return this.chain[this.chain.length - 1];
  }

  // Adds new block
  addNewBlock(newBlock){
    newBlock.previousHash = this.getLastBlock().hash;
    newBlock.hash = newBlock.getHashValue();
    this.chain.push(newBlock);
  }

  // It checks if the blocks are chained properly and valid
  validateChain(){
    for(let i = 1; i < this.chain.length; i++){
      let prevBlock = this.chain[i-1];
      let currBlock = this.chain[i]

      // Check if each block's hash value was not modified
      if(currBlock.hash !== currBlock.getHashValue()){
        return false;
      }
      
      // Check if the blocks are chained correctly
      if(currBlock.previousHash !== prevBlock.hash){
        return false;
      }
    }
    return true;
  }
}

Let’s go through all of the features of this class.

  • constructor defines the chain as an array
  • getFirstBlock creates the initial block in the chain. This first block is usually called the Genesisblock. We need to create it at the beginning manually
  • getLastBlock returns the latest block in the chain. We need to know this to connect the new block to the chain
  • addNewBlock is self-explanatory. It adds a new block to the chain
  • validaChain checks if the chain is valid

We can test our classes to make sure that we are not missing anything

const USDevCoin = new USDevBlockchain();
USDevCoin.addNewBlock(new  Block(1, {amount:  2}, new  Date()));
USDevCoin.addNewBlock(new  Block(2, {amount:  5}, new  Date()));
console.log(JSON.stringify(USDevCoin))

We can test the validation function as well.

const  USDevCoin  =  new  USDevBlockchain();
USDevCoin.addNewBlock(new  Block(1, {amount:  2}, new  Date()));
USDevCoin.addNewBlock(new  Block(2, {amount:  5}, new  Date()));

console.log(USDevCoin.validateChain()); // Prints "true"

USDevCoin.chain[1].payload  = {amount:  290}; // Someone tampers with the chain

console.log(USDevCoin.validateChain()); // Prints "false"

Mining

The current state of the application is not only incomplete but also fragile. Because it allows us to add new blocks to the chain very quickly, spammers can take advantage of this weakness and try to add a huge number of blocks at the same time and eventually break the system. Or the whole chain could be overwritten with a powerful machine. To prevent all of these from happening, we need to implement a method to enforce the system to wait for a certain amount of time before adding a new block to the chain.

For example, Bitcoin requires the hashes to have a specific number of zeros at the beginning. That number is also called the difficulty. It is hard for the machines to find the hash value with the exact amount of zeros at the beginning. So it will take time and tremendous computational power to come up with that value. Since the whole system is distributed, there are a bunch of networks competing against each other to find the correct value. The good thing about mining is that even though it takes a long time to process, it is swift and easy to verify if the work was completed correctly. The entire step is called proof-of-work. Now let us implement it in our code.

In order to add the proof of work step to the system, we need to add a new function to the Block class. This function basically has a while loop which does not stop until it matches the requirement we specify in the arguments.

class Block {
	constructor(index, payload, timestamp, previousHash = ""){
		this.index = index;
		this.payload = payload;
		this.timestamp = timestamp;
		this.previousHash = previousHash;
		this.hash = this.getHashValue;
		this.nonce = 0;
	}
	// .........
	mineNewBlock(difficulty){
		 while(this.hash.substr(0, difficulty) !== Array(difficulty + 1).join("0")){
		   this.nonce++;
		   this.hash = this.getHashValue();
		 }
	}
}

mineNewBlock function takes difficulty as a parameter. The difficulty is another term used in the blockchain world. In simple terms, it defines the level of difficulty to mine new blocks. Bitcoin for example is designed to take about 10 minutes to mine a new block. That timeframe could be increased or decreased by manipulating the difficulty parameter.

The while loop waits until the hash generated has the specified number of zeros at the beginning given in the difficulty property.

Then we have to modify the addNewBlock function to include the newly created function in the Block class. While calling the mineNewBlock function, we send the difficulty defined in the constructor.

class USDevBlockchain {
  constructor(){
    // Chain is an array of blocks
    this.chain = [this.getFirstBlock()];
    this.difficulty = 3;
  }
  // .....
  // Adds new block
  addNewBlock(newBlock){
    newBlock.previousHash = this.getLastBlock().hash;
    newBlock.mineNewBlock(this.difficulty);
    this.chain.push(newBlock);
  }
  // ....
}

Transactions and Rewards

As the name of our blockchain USDevCoin indicates, we are going to use our system for making a cryptocurrency. The most critical part of the cryptocurrencies is the ledger of transactions. Coins get transferred from one user to another, and that action gets recorded as a single transaction. However, one transaction alone cannot be stored as a whole block in the chain. Because of the proof-of-work security layer we have in place.

Again, going back to Bitcoin. We earlier mentioned that it takes about 10 minutes to mine a single block. But in 10 minutes we cannot process only one transaction. That would be an incredibly useless system. So there are thousands of transactions happening within that timeframe. While the network waits for about 10 minutes, those transactions get added to a queue and stay as pending transactions. Once a new block gets mined, all of the pending transactions will be included in that new block and the block is added to the chain.

It means that we have to modify our Block class to include an array of transactions, instead of just a random data object.

// chain.js
const SHA256 = require("crypto-js/sha256");

class Transaction {
  constructor(fromAddress, toAddress, amount){
    this.fromAddress = fromAddress;
    this.toAddress = toAddress;
    this.amount = amount;
  }
}

class Block {
  constructor(transactions, timestamp, previousHash = ""){
    this.previousHash = previousHash;
    this.timestamp = timestamp;
    this.transactions = transactions; // Data -> Transactions
    this.hash = this.getHashValue();
    this.nonce = 0;
  }

  getHashValue() {
    return SHA256(
      this.previousHash + 
      this.timestamp + 
      JSON.stringify(this.transactions) +
      this.nonce
    ).toString();
  }
  //...
}

Then in our USDevBlockchain class we need to make some drastic modifications. Let’s write the code first and then we will go through each addition on by one.

class USDevBlockchain {
  constructor(){
    // Chain is an array of blocks
    this.chain = [this.getFirstBlock()];
    this.difficulty = 3;
    this.pendingTransactions = [];
    this.rewardForMiners = 20;
  }
  //....
  mineBlockForPendingTransactions(minerAddress){
    let newBlock = new Block(this.pendingTransactions, new Date(), this.getLastBlock().hash);
    newBlock.mineNewBlock(this.difficulty);
    this.chain.push(newBlock);

    // When a new block is mined, reward the miner
    // But the reward will be available with the next block
    this.pendingTransactions = [
      new Transaction(null, minerAddress, this.rewardForMiners)
    ];
  }

  addTransactionToList(transaction){
    this.pendingTransactions.push(transaction);
  }

  getWalletBalance(address){
    let bal = 0;
    for(let block of this.chain){
      for(let t of block.transactions){
        if(t.fromAddress === address){
          bal -+ t.amount;
        }
        if(t.toAddress === address){
          bal += t.amount;
        }
      }
    }
    return bal;
  }
  // .....
}
  1. We added the pendingTransactions property, which will store an array of transactions that are still waiting to be included in a new block
  2. rewardForMiners property defines the number of coins that will be given as a reward for mining the blocks. Since mining requires a lot of computations and machine power, the miners must be compensated for their work.
  3. addTransactionToList function takes a transaction record and adds it to the list of pending transactions
  4. mineBlockForPendingTransactions function grabs the list of pending transactions and adds them into the newly mined block when it is completed. Also, once the block is mined, the reward coin for the miner will be stored as a pending transaction. Which means is not available right away. It will be given to the miner on the next completion of mining a new block.
  5. getWalletBalance returns the current balance of an address

Transaction signature

Currently, there is a massive problem with our cryptocurrency system: anyone can use any coin in the network. In other words, people can spend the coins that are not even theirs.

To fix this issue, we need to sign each transaction with a private key. By signing I mean adding a signature property to each transaction. So that when we do the calculations to get the wallet balance, we know whom that transaction belongs to. We can get the private key by utilizing the elliptic module.

Let’s get the public and private keys first. In the main project folder run npm i --save elliptic, create a new file called key.js and add the following code.

const EC = require("elliptic").ec;
const ec = new EC("secp256k1");

const keyPair = ec.genKeyPair();
const publicKey = keyPair.getPublic("hex");
const privateKey = keyPair.getPrivate("hex");

console.log("Public: " + publicKey); // Wallet address
console.log("Private: " + privateKey); // Used to sign

secp256k1 algorithm is actually used in Bitcoin to generate keys. Once we run node key.js we will see two keys on the console: one private and one public.

Public: 0419034253dc7f431983904da1adba98fb766a1669f7b8c55d03fb4d2381a1340b88d52c4f26936cab7ee6473285b2d891ad0552ceb1431fd7fab36ca4bfbf4769
Private: c6e9fb1a2b8954e3af2f92ba4ddfb7f8328f6288f4c53f93e7c6aca0a29148b9

Private key should never be shared with others because it is used to sign transactions. Public key serves as a wallet address, so it can be shared with the public.

Next we need to add a few modifications to the chain.js file.

First we need to change the Transaction class to reflect the signing process.

class Transaction {
  constructor(fromAddress, toAddress, amount){
    this.fromAddress = fromAddress;
    this.toAddress = toAddress;
    this.amount = amount;
  }

  getHashValue(){
    return SHA256(
      this.fromAddress + 
      this.toAddress + 
      this.amount
    ).toString();
  }

  signTransaction(key){
    if(key.getPublic("hex") !== this.fromAddress){
      throw new Error("Invalid signature");
    }
    this.signature = key.sign(this.getHashValue(), "base64").toDER("hex");
  }

  isTransactionValid(){
    if(this.fromAddress === null) return true;
    if(!this.signature ||  this.signature.length === 0){
      throw new Error("No signature was found.");
    }

    const publicKey = ec.keyFromPublic(this.fromAddress, "hex");
    return publicKey.verify(this.getHashValue(), this.signature);
  }
}

signTransaction and isTransactionValid functions add a signature to each transaction, and verify the existing ones with the help of elliptic node module.

And in the Block class, we can add a new function to validate all the transactions that block holds.

class Block {
  // ......
  hasValidTransactions(){
    for(const t of this.transactions){
      if(!t.isTransactionValid){
        return false;
      }
    }
    return true;
  }
}

Now, let’s create an index file to test all of the code.

Make sure to export the classes from the chain.js file.

const EC = require("elliptic").ec;
const ec = new EC("secp256k1");
const { USDevBlockchain, Transaction } = require("./chain");

const key = ec.keyFromPrivate("c6e9fb1a2b8954e3af2f92ba4ddfb7f8328f6288f4c53f93e7c6aca0a29148b9");
const walletAddress = key.getPublic("hex");

const USDevCoin = new USDevBlockchain();
const t1 = new Transaction(walletAddress, "someone else's wallet address", 2);
t1.signTransaction(key);
USDevCoin.addTransactionToList(t1);

USDevCoin.mineBlockForPendingTransactions(walletAddress);

const t2 = new Transaction(walletAddress, "someone else's wallet address", 2);
t2.signTransaction(key);
USDevCoin.addTransactionToList(t2);

USDevCoin.mineBlockForPendingTransactions(walletAddress);

console.log("My balance: " + USDevCoin.getWalletBalance(walletAddress));

//Prints: My balance: 96

Link to GitHub

In the next and last part of this blog, we will create a neat user interface that will implement the blockchain system we have built.

Cheers!

Exploring React Native – Part 3

Previously, in “Exploring React Native (Continued Part 2)”, we continued to work on our simple app. The code for the app was long and was all located in one file after the article, “Exploring React Native (Continued Part 1)”. Being that React Native uses native components as building blocks, we decided to break down each part of the app into custom components. There was a custom component for our images, texts, and buttons. Then we used React Native’s View component to create cards for each subject and learned the different ways to style components.

In this article, we will continue to work on our project implementing the TextInput component provided by React Native. Then we will use some JavaScript functions to convert the counter into the correct data type.

Let’s get started!

Built In Components

I will be working on a Mac using Visual Studio Code as my editor, run the app on the iOS simulator and will be working with the “FirstRNProject” project. If you are using Windows or are targeting Android, I will test the app on the Android emulator at the end of the article. This code will also work if you are using Expo and will also be tested later on.

If you are starting with a new React Native or Expo project or didn’t follow the previous article, here is the project structure:

Here is the code:

App.js

import React, { Component } from 'react';
import Main from './src/screens/Main'
class App extends Component {
render() {
return <Main />
}
}
export default App;

Main.js

import React, { Component } from 'react';
import { ScrollView, StyleSheet, View } from 'react-native';
import OurImage from '../components/OurImage';
import Question from '../components/Question';
import Counter from '../components/Counter';
import OurButton from '../components/OurButton';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class Main extends Component {
state = {
raccoons: 0,
pigeons: 0
};
//Raccoon Functions
addRaccoons = () => {
this.setState({
raccoons: this.state.raccoons + 1
})
}
removeRaccoons = () => {
if(this.state.raccoons !== 0){
this.setState({
raccoons: this.state.raccoons - 1
})
}
}
//Pigeon Functions
addPigeons = () => {
this.setState({
pigeons: this.state.pigeons + 1
})
}
removePigeons = () => {
if(this.state.pigeons !== 0){
this.setState({
pigeons: this.state.pigeons - 1
})
}
}
render() {
return (
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter count={this.state.raccoons} />
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addRaccoons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter count={this.state.pigeons} />
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>
</View>
</View>
</ScrollView>
)
}
}
export default Main;

OurImage.js

import React from 'react';
import { Image, StyleSheet } from 'react-native';
const styles = StyleSheet.create({
image: {
height: 200,
width: 200,
alignSelf: 'center'
}
})
const OurImage = ({ imageSource }) => (
<Image style={styles.image} resizeMode='contain' source={imageSource} />
);
export default OurImage;

Question.js

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
question: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Question = ({ question }) => (
<Text style={styles.question}>{question}</Text>
);
export default Question;

Count.js

import React from 'react';
import { StyleSheet, Text } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<Text style={styles.number} >{count}</Text>
);
export default Counter;

OurButton.js

import React from 'react';
import { StyleSheet, Text, TouchableOpacity } from 'react-native';
const styles = StyleSheet.create({
buttonStyling: {
width: 150,
borderRadius: 10,
margin: 5,
alignSelf: 'center'
},
buttonText: {
fontSize: 30,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60'
},
})
const OurButton = ({ buttonColor, onPressed, text }) => (
<TouchableOpacity onPress={onPressed} style={[styles.buttonStyling, {backgroundColor:buttonColor}]} >
<Text style={styles.buttonText}>{text}</Text>
</TouchableOpacity>
);
export default OurButton;

Here is how the app looked:

The app looks great, the code is clean and we have custom components. What we will be doing is giving the user the option to change the counter with the keyboard. This will be done with React Native’s TextInput component. According to React Native’s documentation, “A foundational component for inputting text into the app via a keyboard. Props provide configurability for several features, such as auto-correction, auto-capitalization, placeholder text, and different keyboard types, such as a numeric keypad.”

Open the “Counter.js” file and import TextInput from React Native. Then delete the Text component and replace that with the TextInput component like this:

import React from 'react';
import { StyleSheet, Text, TextInput } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<TextInput />
);
export default Counter;

Save the file and reload.

Hey what happened to the zero? Well, TextInput requires a that a value prop be passed. Give the component a prop of “value” that is equal to the count.

<TextInput value={count} />

Nothing appears. If you look at the bottom of the screen, you will see that there is a warning. The warning says that the value of TextInput must be a string. In order for the TextInput component to work, we will need to use some JavaScript. The plan is to change the data from a number to a string. Then when the buttons are pressed we will convert the string to number then back to string. Hopefully this works.

Start by changing the data in state from a number to a string. Go to “Main.js” and simply put the quotes around the zero, like this:

state = {
raccoons: '0',
pigeons: '0'
};

Save and reload the file to see that the zeroes appear again.

We have lost our styling. Let’s add styling to the TextInput component in “Counter.js” by passing the style prop.

const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count }) => (
<TextInput
style={styles.number}
value={count}
/>
);

If we save the file and reload the app, the zeroes will appear with the styling we had before.

But if you try using the “PLUS” button, it will concatenate a one to the end of the text every time you press it. And if you use the “MINUS” button, the text will disappear and a warning will pop up.

For the raccoon section I used the “PLUS” button and for the pigeon section I used the “MINUS” button. These were my results:

Go to “Main.js” and we will start with the “addRaccoons” function. Create a variable named “num”, before “this.setState”. This variable will be equal to “parseInt({this.state.raccoons}) + 1”.  JavaScript comes with some built in functions, similarly to how React Native comes with built in components. We are using the function “parseInt()” to convert “{this.state.raccoons}” from a string to a number, then add one. After, we will set “num” equal to “num.toString()”. Here we are using another JavaScript function “toString()”. This function converts a number to a string. Now that “num” is a string again, we can now use “this.setState” to have “raccoons” set to “num”.

//Raccoon Functions
addRaccoons = () => {
let num = parseInt(this.state.raccoons) + 1;
num = num.toString();
this.setState({
raccoons: num
})
}

Save the file and reload the app:

Cool! The button is working and we can implement this to the “addPigeons” function, just remember to use “{this.state.pigeons}”. Now the “PLUS” buttons for the raccoon and pigeon section will work but the “MINUS” will still cause the app to give a warning.

//Pigeon Functions
addPigeons = () => {
let num = parseInt(this.state.pigeons) + 1;
num = num.toString();
this.setState({
pigeons: num
})
}

Go to “removeRaccoons” and start by creating a variable named “num”. This variable will be equal to “parseInt(this.state.raccoons)”. Then replace “{this.state.raccoons}” with “num” in the if condition. If “num” is not equal to zero, set “num” to “num – 1” and then convert it to a string. Last thing to do is set “{this.state.raccoons}” to “num”.

Here is the code:

removeRaccoons = () => {
let num = parseInt(this.state.raccoons);
if(num !== 0){
num = num - 1;
num = num.toString();
this.setState({
raccoons: num
})
}
}

The counter for the raccoon is working again. Let’s go and add this logic to the “removePigeons” function. Again, remember to use “this.state.pigeons” or the button will not work correctly.

Here are the four functions for the raccoon and pigeon buttons:

//Raccoon Functions
addRaccoons = () => {
let num = parseInt(this.state.raccoons) + 1;
num = num.toString();
this.setState({
raccoons: num
})
}
removeRaccoons = () => {
let num = parseInt(this.state.raccoons);
if(num !== 0){
num = num - 1;
num = num.toString();
this.setState({
raccoons: num
})
}
}
//Pigeon Functions
addPigeons = () => {
let num = parseInt(this.state.pigeons) + 1;
num = num.toString();
this.setState({
pigeons: num
})
}
removePigeons = () => {
let num = parseInt(this.state.pigeons);
if(num !== 0){
num = num - 1;
num = num.toString();
this.setState({
pigeons: num
})
}
}

Next what we want to do is choose the keyboard type of TextInput component. By default, the keyboard consist of the alphabet but we don’t need letters.

Go back to “Counter.js” and pass the TextInput component the following prop, “keyboard=’numeric’”.

<TextInput
style={styles.number}
value={count}
keyboardType='numeric'
/>

To test that the correct keyboard appears, save and reload the app. Then press on zero and the keyboard will appear. If the keyboard does not appear in the iOS simulator, click on “Hardware” menu and head to “Keyboard”. Then select “Toggle Software Keyboard”. Or on your computer’s keyboard, press “Command” and “K”.

It looks fine when editing the raccoon’s counter but we can’t see the text field when editing the pigeon’s counter. We need the text fields to move up when the keyboard pops up. Luckily, React Native has a component named KeyboardAvoidingView which we can use. This component, according to the React Native documentation, “is a component to solve the common problem of views that need to move out of the way of the virtual keyboard. It can automatically adjust either its position or bottom padding based on the position of the keyboard.”

First, import KeyboardAvoidingView from React Native. Then inside the render function, wrap the entire JSX code with KeyboardAvoidingView. Give this component a style prop equal to “flex: 1” and a behavior prop equal to “padding”.

import { KeyboardAvoidingView, ScrollView, StyleSheet, View } from 'react-native';
<KeyboardAvoidingView style={{ flex: 1 }} behavior="padding">
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter count={this.state.raccoons} />
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addRaccoons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter count={this.state.pigeons} />
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>

Save the file and reload the app. Try selecting the text input for the pigeon and notice that it moves up above the keyboard.

Much better! Now, we need to work on the handling the user input. If you are to press a number, you will see that the zero remains. TextInput has a prop called onChangeText, which we need to implement.

Go to “Counter.js” and add the prop onChangeText, we will set this equal to “handleText”. “handleText” will be a prop that is passed to “Counter.js” from “Main.js”

Counter.js

const Counter = ({ count, handleText }) => (
<TextInput
style={styles.number}
value={count}
keyboardType='numeric'
onChangeText={handleText}
/>
);

Then in “Main.js”, head to the Counter component and give it the prop “handleText”. We will have this prop equal an arrow function which takes the users input and sets the state equal to it.

Main.js

<Counter
count={this.state.raccoons}
handleText={(text) => this.setState({ raccoons: text})}
/>

Now when we use the keyboard to enter a number, the text will change.

Cool! We can change the text by pressing on the keyboard. Yes, the zero is front of the numbers doesn’t look nice but it is working. We can even use our buttons to increase or decrease the value. We won’t worry about the zero for now, instead let’s implement the “handleText” for the pigeon section.

<Counter
count={this.state.pigeons}
handleText={(text) => this.setState({ pigeons: text})}
/>

Save the file and reload to test the pigeon section.

Great! It works here too. At this point we know the app works on the iOS simulator, let’s go ahead and test it on Android first then in Expo.

Here is how it looks on Android:

Woah! That was unexpected. If we go back to the React Native document on behavior prop for KeyboardAvoidingView, it states that, “Note: Android and iOS both interact with this prop differently. Android may behave better when given no behavior prop at all, whereas iOS is the opposite.” Therefore, it is the behavior prop that is passed to KeyboardAvoidingView that is causing the spacing between the keyboard and the text input.

What we can do is check on which phone the app is running. We first import Platform and create a variable called “paddingBehavior”. This variable will check to see if the app is running on iOS and if it is then “paddingBehavior = ‘padding’”, else it is equal to ‘’. Using this variable, have “behavior={paddingBehavior}”.

import { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, View } from 'react-native';
const paddingBehavior = Platform.OS === 'ios' ? 'padding' : '';
<KeyboardAvoidingView style={{ flex: 1 }} behavior={paddingBehavior}>

Save the file and reload the app.

Works much better! Time to test on Expo. After copying the code into the Expo project and running the app, here is what I got:

Nice! The app is working great in Expo as well. Here are the two files worked on throughout this article.

Main.js

1. import React, { Component } from 'react';
2. import { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, View } from 'react-native';
import OurImage from '../components/OurImage';
import Question from '../components/Question';
import Counter from '../components/Counter';
import OurButton from '../components/OurButton';
const paddingBehavior = Platform.OS === 'ios' ? 'padding' : '';
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#bff0d4',
paddingTop: 20
},
cardStyle: {
borderColor: '#535B60',
borderWidth: 2,
margin: 20,
borderRadius: 10,
},
buttonRow: {
flexDirection: 'row',
alignSelf: 'center'
}
});
class Main extends Component {
state = {
raccoons: '0',
pigeons: '0'
};
//Raccoon Functions
addRaccoons = () => {
let num = parseInt(this.state.raccoons) + 1;
num = num.toString();
this.setState({
raccoons: num
})
}
removeRaccoons = () => {
let num = parseInt(this.state.raccoons);
if(num !== 0){
num = num - 1;
num = num.toString();
this.setState({
raccoons: num
})
}
}
//Pigeon Functions
addPigeons = () => {
let num = parseInt(this.state.pigeons) + 1;
num = num.toString();
this.setState({
pigeons: num
})
}
removePigeons = () => {
let num = parseInt(this.state.pigeons);
if(num !== 0){
num = num - 1;
num = num.toString();
this.setState({
pigeons: num
})
}
}
render() {
return (
<KeyboardAvoidingView style={{ flex: 1 }} behavior={paddingBehavior}>
<ScrollView style={styles.container}>
{/* Raccoon */}
<View style={styles.cardStyle}>
<OurImage imageSource={require('../img/raccoon.png')} />
<Question question='How many raccoons did you see last night?' />
<Counter
count={this.state.raccoons}
handleText={(text) => this.setState({ raccoons: text})}
/>
{/* Raccoon Button */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addRaccoons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removeRaccoons}
text='MINUS'
/>
</View>
</View>
{/* Pigeon */}
<View style={[styles.cardStyle, {marginBottom: 60}]}>
<OurImage imageSource={{ uri: 'https://cdn.pixabay.com/photo/2012/04/02/12/43/pigeon-24391_1280.png' }} />
<Question question='How many pigeons did you see today?' />
<Counter
count={this.state.pigeons}
handleText={(text) => this.setState({ pigeons: text})}
/>
{/* Pigeon Buttons */}
<View style={styles.buttonRow}>
<OurButton buttonColor='#9FC4AD'
onPressed={this.addPigeons}
text='PLUS'
/>
<OurButton buttonColor='#BAAAC4'
onPressed={this.removePigeons}
text='MINUS'
/>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
)
}
}
export default Main;

Counter.js

import React from 'react';
import { StyleSheet, Text, TextInput } from 'react-native';
const styles = StyleSheet.create({
number: {
fontSize: 60,
fontWeight: 'bold',
textAlign: 'center',
color: '#535B60',
padding: 10
},
})
const Counter = ({ count, handleText }) => (
<TextInput
style={styles.number}
value={count}
keyboardType='numeric'
onChangeText={handleText}
/>
);
export default Counter;

These two files were the only files we worked on in this article, if you need the others, please check the beginning of the article.

Great job! We added the TextInput component to allow a user to use the keyboard to edit the counter data. We also used some JavaScript functions to convert the counter from a string to a number and back to a string because TextInput only worked with strings. The buttons still work and can be used to controlled the counter. We also added KeyboardAvoidingView to allow us to always see the text input field when the keyboard pops up. This caused an issue on Android because different props have different affects on specific platforms. To resolve this issue, we created a variable that checked the platform on which the app is running on.

Until next time, please try to go over the code and make changes to better understand the topics that were covered here.

Hash Tables Simplified

Hash table is a data structure designed for quick look ups and insertions. On average, its complexity is O(1) or constant time. The main component of a hash table is its hash function. The better the hash function, the more accurate and faster the hash table is. High level process of implementing a hash table is as follows: data is sent to a hash function where it gets evaluated and assigned an index number in an array. The hashing algorithm stores the data under the designated index with a pointer. When a lookup is requested for the same data, the algorithm sends the data to the same hash function and retrieves the index of the data in constant time.

hash table which is also known as hash map, dictionary or just map is a data structure that arranges data for quickly looking up values with a given key.

Average run time complexity of a hash table is O(1) or constant time.

Hash tables are very similar to arrays. Arrays store values in sequential order and they have indices that can be used to look up values instantly. However, arrays have several restrictions: First of all, the indices are generated by the computer in sequential order. Second, if we want to add a value at the beginning or in the middle of the array, we need to move the rest of the values, which requires O(n) steps in the worst case scenario. And in some cases, when we are using non-dynamic arrays, their sizes are fixed.

Hash tables are like giving super powers to arrays. First, instead of relying on sequential indices, we use a function that turns keys into indices. That function is known as the hash function. Hash function is a special function that takes in a key and spits out an index. There are different ways of making hash function and we will look into them later. So then we store the values under that specific index. Later we can use the same function to get the indices and look up values in constant time just like with arrays.

Example

Let’s look at an example case where using a hash table would be a good fit. Let’s say there is a list of students at a university with basic information. |Name|Major|Year| |-|-|-| |Bob|Math|2| |Sam|Biology|1| |Lisa|Art|3|

Now we are asked to organize this data for quick look ups and insertions. Using a hash table we can easily accomplish this task. First we have to pick a key from the list to identify each record. Typically, it is required to choose some value that is unique for each element. But for simplicity purposes we just pick the student names. So we have an array with 5 slots or buckets. Instead of assigning each record in order, we use a hash function to determine which slot each record goes to. We take Bob and give it to the hash function hash('Bob') and the function returns us an index value of 0, for example. We store Bob’s details under the index 0. Then we send Sam to the hash function, the functions tells us to store Sam’s details in slot 4. We do the same for Lisa and store her information in bucket 3.

Hash Function

Now let’s discuss what happens in our hash function. There are countless ways of making hash functions. It is usually preferred to use the ones on the internet which were tested by many people. However, for the sake of understanding the details under the hood, we can implement a simple one here.

Hash function logic We take ASCII value of each character and add them up.

Total %5
B o b
66 111 98 275 0
S a m
83 97 109 289 4
L i s a
76 105 115 97 393 3

For example, for Bob the sum of ASCII values would be 275. Since we have only 5 slots in our array we have to reduce the number to a smaller one. We can use a modulo operator to do that. 275 % 5 = 0

That means we store Bob’s details in slot 0.

Collisions

Remember we said the run time complexity of a hash table is constant – O(1) earlier? Well, its not entirely true. In the worst case scenario, complexity can be as bad as O(n). Main reason for that is the collisions. Collision is a situation when hash function outputs a duplicate index number.

For example, if we send the name Mia to our previous hashing function, it returns index 4. However, that slot is already occupied.

So there are 2 common ways of handling this issue. First one is called Linear Probing. With linear probing, we look at the given index, and if its occupied we go to the next available slot. In our example, there is no next slot. So in this case, we have to wrap around. Meaning we start from the beginning looking for an empty spot. 0 is also taken. We move to slot 1. That place is empty. We insert Mia at index 1. We keep repeating this process for other values if any collisions occur.

Second method is called Chaining. Here we use Linked list to handle duplicate index issues. If you don’t know what a linked list is, here is a good source to read about it. For this method to work, the hash table needs to be properly implemented. All slots should be pointing to the head of the linked list. Then when there is a collision we store the value in the next chain of the linked list. During look ups we need to ensure to check for all nodes by iterating through the list. That is why run time complexity sometimes can be a O(n)

Hash Table in JavaScript

In JavaScript hash table is called Object.

const hash_map = {
	'key':'value'
};

Values in objects could be any type: string, array, integer or even another object. For example, to create an object for the data we had earlier we do the following

const map = {
	Bob: {
		name: 'Bob',
		major:'Math',
		year: 2,
	},
	Sam: {
		name: 'Sam',
		major:'Biology',
		year: 1,
	}
};

Insertion

If we want to insert new key value pairs in the object, we can do it in two ways. First we can use dot method. Second way is similar to **array look up

map['Lisa'] = {
	name: 'Lisa',
	major':'Art',
	year: 3,
};

// OR

map.Lisa = {
	name: 'Lisa',
	major':'Art',
	year: 3,
};

Removal

delete map.Bob;

// OR

delete map['Bob']

Update

map.Lisa.year = 4;
// Or
map['Lisa']['year'] = 4;

Look up

console.log(map.Sam.major);
// Output: 'Biology'

// OR

console.log(map['Sam']['major']);
// Output: 'Biology'

Cheers

Strapi.js – A new way to build Node.js APIs

Strapi.js is the most advanced Node.js Framework and Headless CMS out there. Even though it is not as popular as Express.js, it has the power to save weeks of development time for teams working on Node.js applications. With built-in admin panel and Koa.js under the hood, strapi can help you build your next awesome product.

Pre-requisites:

  • Basic knowledge of JavaScript
  • Node version 10.x+

Outline

  1. Intro
  2. What is Strapi.js?
  3. Features
  4. Get Started!

Intro

Since the launch of Node.js in 2011, we have seen several frameworks that were built on top of this amazing JavaScript runtime environment. Node.js allowed devs to write fast and robust APIs in minutes. Frameworks gave it super powers. The most popular framework for Node.js is and has been Express.js. Main reason for its popularity is its simplicity and minimalistic style. It accelerates Node.js project development even more. Besides Express.js, there are other frameworks such as Hapi, Koa, Meteor and Sails which have found their way into the hearts of developers. In this article, I would like to write about one Node.js framework that has been immensely underrated in the Node community, but has the power to save weeks of development – Strapi.js. Just stick with me here and we will look at the features of this powerful framework and explore what we can do with it.

What is Strapi?

Strapi is an open source Headless CMS based on Node.js. It comes with a flexible and customizable admin panel to build fast and secure content APIs. And it is used by thousands of companies around the world such as IBMWalmartDiscovery and others.

But what is a headless CMS in the first place?

Headless CMS is a type of content management system, such as WordPress, but without the view layer/front end (the head). It means we are not tied to one way of displaying data. We can just plug it into React, Angular or Vue alike view layers. It just provides the APIs and CRUD UI and it can be used with websites, mobile apps widgets, native apps etc. Strapi supports RESTful APIs and also GraphQL.

Features

There are a lot of reasons why you should give Strapi a try on your next project. Below we will go through the main ones.

Koa.js

Strapi is actually built on top of Koa.js, another Node.js framework made by the team who created the Express.js. Koa is a small and more expressive tool which is predicted to be the next generation Node.js framework. Having Koa.js under the hood makes Strapi future proof.

Plugin based

Almost everything in Strapi is plugin. Some of the plugins are installed by default upon creation of the project. Others can be created based on user needs. The real advantage of plugin based framework is that everything is customizable and extensible. Don’t like how the Admin Panel looks, go ahead, customize it. Can’t find the right plugin you are looking for, just create one!

Robust Content Management

Strapi comes with a built-in content management plugin that allows to easily CRUD content, including media files. Admin user interface is super user friendly and anyone can get started with it within minutes. The fact that the content management feature is actually a plugin means that it can be extended to fit any business needs.

React.js

Strapi Admin Panel is built using React.js and the source code is right there inside the project for you to modify if need be. Advanced functionalities of React allows Strapi to deliver amazing user experience.

Content Type Structure

Designing content type structures is made easy by available field types in the Content Type Builder plugin of the Admin Panel. The following types are accessible right out of the box:

  • Text Paragraphs
  • Boolean
  • Email
  • Date
  • Password
  • List of choices
  • Media files
  • JSON
  • String
  • Relation to other Content Types
  • Number

Similar to other plugins, content type builder plugin is also extensible. You can add your own field types to the list!

Secure and flexible APIs

APIs in Strapi can be requested using GraphQL or REST. Calls to all endpoints are secured by default, utilizing the Authentication and Permissions plugin. More often than not, we want our websites or apps to be used by people with different roles. And developing your own RBAC (Role Based Authentication System) can take weeks of development. Strapi provides that functionality out of the box!

Get Started!

Before we get started with Strapi, make sure you have the latest version of Node (10.x and above)

To install Strapi globally on your machine run the following

npm install strapi@alpha -g

Now we can start our new project.

Sample app – Strapi Cycle Bike Rental

We are going to build a backend for a simple bike rental shop using Strapi.js. We want to have APIs to manage clients, bike inventory and orders.

  • /users – to manage the client base
  • /bikes – to manage the bike inventory
  • /orders – to keep track of the orders

The beauty of the framework comes with the “Out of the box” configurations. Once we set up the server and add new models, necessary endpoints for CRUD operations get generated automatically. We can just start using them. Indeed, the APIs can be modified depending on the requirements.

Steps

Step 1

Run the following command to set up a new Strapi project

$ strapi new strapi_cycle

When prompted with the options in the terminal, we can decide which database we want to use and the kind of configurations we want to have. For simplicity, we will be using a local MongoDB database.

- Choose your main database: MongoDB
- Database name: strapi_cycle
- Host: 127.0.0.1
- +srv connection: false
- Port (It will be ignored if you enable +srv): 27017
- Username: <empty>
- Password: <empty>
- Authentication database (Maybe "admin" or blank): strapi_cycle
- Enable SSL connection: false

Note: If you have any issues connecting to your database, make sure you are using correct username/password. Also, leaving the Authentication databasequery blank can cause problems.

Step 2

Navigate to the project folder and run

$ strapi start

Command will start the server on port 1337. So if you navigate to localhost:1337 you should see a page similar to this:

Step 3

In order to create the endpoints for our bike rental shop, we navigate to the built-in admin panel. Click on the /admin link on the welcome page and you should be redirected to registration page.

Since there are no users in the database initially, the user you register first on the this page will have an admin role. Later on when we add more users without specifying the role, they will have a Public role by default. New roles can be added in the Roles and Permissions menu of the sidebar.

Step 4

Click on the Content Type Builder plugin and you will see that there are 3 content types already created by default. Those content types belong to the Roles & Permissions plugin. Since we do not need to use roles or permissions for our backend, we will just ignore the roles and permissions types for now. Lucky for us, the user content type is already there.

Click on the Add new content type button and enter the details for the model. First we create the bike model.

Step 5

Once we create the content type, next we have to add new fields. Click on Add new field button and add new fields for our bike model.

Name Type Value
model String
rate Number
status Enumeration Available,Taken,Broken

Step 6

Repeat steps 4 and 5 for Order model with the following fields

Name Type
rental_start Date
rental_end Number
cost Integer
user Relation with User
bikes Relation with Bike

An important thing to note here is that creating relations between models is ridiculously easy with Strapi.js. When selecting the type of the field for a model, just select the Relation type and you will be given options on how 2 entities should be related to each other.

In our case, an order can belong to a single user and a many bikes belong to many orders. So their relationship will be as follows:

Step 7

That’s it! We are pretty much done creating the APIs for users, bikes and orders. In order to see if they are working properly, let’s add some records and make calls to the newly created endpoints.

On the top of the sidebar, we have a list of our models. Click on each of them and add new records with dummy values.

Step 8

Now we can test our APIs using Postman. If you do not have this awesome tool installed on your machine, please do yourself a favor and download it from here.

Before we can make calls to the endpoints, we need to acquire a token from server. In order to do that, we will send a POST message to localhost:1337/auth/login with the following payload in the body

{
	"identifier":"sardor",
	"password":"<your_password>"
}

After that we can use the token in the header of each API call

Response body for /orders

[
    {
        "rental_time": "2020-04-13T13:00:00.000Z",
        "rental_due": "2020-04-12T16:00:00.000Z",
        "cost": 30,
        "bikes": [
            {
                "model": "M001",
                "rate": 10,
                "status": "Available",
                "_id": "5cbb1f03f3dc0d992df68176",
                "createdAt": "2019-04-20T13:30:43.846Z",
                "updatedAt": "2019-04-20T13:30:43.965Z",
                "__v": 0,
                "id": "5cbb1f03f3dc0d992df68176",
                "orders": null
            }
        ],
        "_id": "5cbb1f9cf3dc0d992df68177",
        "createdAt": "2019-04-20T13:33:16.558Z",
        "updatedAt": "2019-04-20T13:33:16.687Z",
        "__v": 0,
        "user": {
            "confirmed": true,
            "blocked": false,
            "name": "",
            "_id": "5cbb1eb7f3dc0d992df68173",
            "username": "jbourne",
            "email": "jbourne@jb.com",
            "provider": "local",
            "__v": 0,
            "role": "5cbb19ea6369dd710e43a720",
            "id": "5cbb1eb7f3dc0d992df68173"
        },
        "id": "5cbb1f9cf3dc0d992df68177"
    }
]

We are getting 200 status code, which means our APIs are working! If you pay attention to the body of the response, relation among the fields are implemented correctly as well.

Link to GitHub | Strapi

Cheers!

Practical guide to build Serverless applications with Netlify and React.js

Serverless technology is taking over the back-end development world. Some businesses are already dumping microservices infrastructure and switching to serverless. However, the learning curve for serverless is pretty steep and it comes with great complexity. Netlify is trying to solve that problem by providing create & drop functions. In this article, we learn about the main concepts of serverless technology and create a sample application using Netlify functions and React.js.

Pre-requisites:

  • Basic knowledge of JavaScript and React
  • React version 16.8+

Since the introduction of AWS Lambda functions in 2014, the word Serverless has been gaining great popularity among businesses and developers. It was told to be the next generation of DevOps after the explosion of containerization. Some people call it the real evolution and say that it will be the future of DevOps. However, the majority has been reluctant to adopt it. They claim that it is not secure enough or requires too much setting up. Which one is more accurate, is everything going to be “serverless” soon or is it just an unjustified hype that will fade away over time?

Either way, we cannot know what will happen in the future. What we can do is to learn about the technology as much as we can and decide if it is a good fit for our development needs or not. Below we will briefly discuss the concepts serverless methodologies and then build a sample application using Netlify functions and React.js.

What is Serverless again?

Serverless is an execution model where cloud providers such as AWS or Azure are responsible for provisioningmaintaining and managing servers for running code. In simpler terms:

  • Serverless or FaaS (Functions as a Service) is a way to run functions and create APIs without setting up your own servers

So there are servers involved in this model. The difference is – cloud providers handle everything related to servers for a fee, and businesses focus on writing functions.

How is this different from Monolithic way of building applications and Microservices?

As we can see from the picture, the monolithic way is usually the easiest way to setup and build, but it creates major issues when it comes to scaling. Microservices are widely used among many large companies nowadays. However, they require great effort to configure and maintain. Serverless can be a great option when implemented correctly.

Advantages and disadvantages of Serverless

Just like any stack, serverless has its own pros and cons. It is up to the businesses to consider all use cases and make an informed decision. Let us take a look at the pros of serverless model.

Advantages

  1. Auto scaling Since servers are managed by the FaaS providers, they (almost) guarantee auto scaling of your applications. No need to load balance or worry about the inbound traffic surge. System can automatically spin up new function instances during rush hours, if necessary.
  2. Pay for what you use Let us say that we have an application used by thousands of people during the day, and no one really uses it at night. With monolithic or microservices models, we pay for every hour our application runs on the servers – 24/7. With serverless model we pay per request. If there are no requests made at night, we don’t pay anything.
  3. Focus on business logic Does serverless mean zero DevOps? Absolutely not. However, it dramatically reduces the amount of work related to infrastructure. FaaS providers take care of most of the tasks which are usually on DevOps engineers’ plates. No need to buy/manage/maintain servers. Businesses can spend more time on core features, user experience and design.

Disadvantages

  1. Cold starts When a serverless function is called for the first time, it may take up to several seconds to execute the function. It can be frustrating if the function is a critical part of the system. However, there are ways to avoid this issue. One one of them is to run cron jobs. Which means setting up a script that gets triggered periodically and calls the function. So that the next time when real requests come in, the function will be “warm” and ready to execute.
  2. Locked in with vendors It would require tremendous amount of work to set up your own FaaS infrastructure. So we are limited to a number of FaaS providers for now. There are currently 3 vendors that are dominating the cloud: AWSAzure and Google Cloud Platform. Once you choose one of the vendors, your application’s fate will depend on the vendor. They can increase or lower the prices as much as they want and change the rules as often as they need. It is not very flexible.
  3. Complexity Admittedly, learning curve for serverless is steep. With auto scalability and fine granularity comes great complexity. There is more wiring to do at the beginning of the project. However, little patience and experimenting can bring huge savings and improve scalability and maintainability.

What are Netlify functions?

Netlify functions are serverless functions that can be deployed along with the rest of your site to create modern and scalable backend.

They are the real revolution in serverless world. Netlify functions are powered by AWS Lambda and require no setup or ops. Typically, when we want to setup an AWS Lambda function, we need to go through more than 20 steps. Such as creating an AWS account, managing service discovery, configuring API gateways and coordinating deployments and more. Netlify functions take care of the setting up part and allow us to just drop the folder with functions in our project and viola! We have a back-end!

Naturally, there is a certain limit set on the number of function calls we can make in a month for free (125k). But if going serverless is the best option for the business, it is totally worth paying extra money for more bandwidth.

All Netlify functions are version controlled and can be written in JavaScript or Go.

Semantic Weather App

In this section we will be building a simple weather app with Netlify functionsReactJS and Semantic-UI

Link to DEMO | GitHub

Tutorial

Step 1

Before we get started, make sure that you have the latest NodeJS, and create-react-app installed on your machine.

First we need to create a React application

$ create-react-app semantic_weather

Then navigate to the project folder and install the following npm modules

npm i --save semantic-ui-react semantic-ui-css node-fetch encoding npm-run-all

Also, the following development dependencies are necessary

npm i --save-dev netlify-lambda http-proxy-middleware dotenv 

Step 2

Create separate folders in /src for components and css.

To get the icons for the weather app, download this set of icons. Copy the /fonts folder from the package into the /src folder of your project.

After you download the icons package, you should also see the css file named weather-icons.min.css in the there. Copy that file into the /css folder we have just created. Also, while you are inside the /css folder, create a new css file named Weather.css and paste the following code in it:

@media only screen and (max-width: 600px) {
  #main-container {
    width: 100%;
    padding-top: 50px;
  }
}

@media only screen and (min-width: 600px) {
  #main-container {
    width: 50%;
    margin: auto;
    padding-top: 50px;
  }
}

.w-icon {
  font-size: 4.5em;
  color: #db3fe2;
}

.w-h1 {
  font-size: 5em;
}

.w-p {
  font-size: 2em;
  margin: 20px;
}

.w-error {
  color: darkred;
}

Step 3

To insure that our pages have access to Semantic-UI css files, we have to add the following line in src/index.js file of our React project:

import  'semantic-ui-css/semantic.min.css';

Also, open your package.json file and make sure it looks similar to this:

// package.json
{
  "name": "semantic_weather",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "encoding": "^0.1.12",
    "node-fetch": "^2.3.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-scripts": "2.1.8",
    "semantic-ui-css": "^2.4.1",
    "semantic-ui-react": "^0.86.0"
  },
  "scripts": {
    "start": "run-p start:**",
    "start:app": "react-scripts start",
    "start:lambda": "netlify-lambda serve src/lambda",
    "build": "run-p build:**",
    "build:app": "react-scripts build",
    "build:lambda": "netlify-lambda build src/lambda",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "devDependencies": {
    "dotenv": "^7.0.0",
    "http-proxy-middleware": "^0.19.1",
    "netlify-lambda": "^1.4.5",
    "npm-run-all": "^4.1.5"
  },
  "proxy": "http://localhost:9000"
}

Step 4

Now we add the main part of the application – Weather component.

Inside the src/components folder, create a new file and name it Weather.js. Add the following code in it:

// src/components/Weather.js

import React, { useState } from "react";
import {
  Header,
  Segment,
  Container,
  Input,
  Form,
  Loader
} from "semantic-ui-react";
import "../css/Weather.css";
import "../css/weather-icons.min.css";
import { useFetchWeather } from '../customHooks';

const Weather = () => {

  const [inputValue, setInputValue] = useState('');
  const [searchValue, setSearchValue] = useState('dallas');
  
  const { data, error, loading } = useFetchWeather(
    '/.netlify/functions/getWeather',
    searchValue
  );

  return (
    <Container id="main-container">
      <Segment raised>
        <Header className="ui basic segment centered">Semantic Weather</Header>
        <Segment>
            <Form onSubmit={() => setSearchValue(inputValue)}>
              <Input 
                  fluid
                  action="Search" 
                  autoFocus 
                  placeholder="e.g. Dallas" 
                  onChange={e => setInputValue(e.target.value)}
                  value={inputValue}
                  size="large"
              />
              {error && <p className="w-error">Please enter a valid city name. (e.g. New York)</p>}
            </Form>
        </Segment>
        <Segment textAlign="center">
            {(!loading && data) ? (
              <div>
                <h1 className="w-h1">{data.temp} °F </h1>
                <div>
                    <i className={`wi wi-owm-${data.weather[0].id} w-icon`}/>
                    <p className="w-p">{data.weather[0].main}</p>
                </div>
                <h1>{data.city}, {data.country}</h1>
              </div>
            ) : <Loader active inline='centered' />}
        </Segment>
      </Segment>
    </Container>
  );
};

export default Weather;

There is one thing missing in the Weather.js file that we have not created yet. useFetchWeather custom hook. This hook will allow us to make a call to the Netlify function we will be creating soon and get weather details for the city provided in the search bar. It is good practice to keep the custom hooks in a separate file. So we create a new file called customHooks.js in /src folder. If you would like to learn more about the React.js custom hooks, checkout this article

// src/customHooks.js

import { useState, useEffect } from "react";

export const useFetchWeather = (url, city) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(false);

  useEffect(() => {
    setLoading(true);
    fetch(url, {
      method: "POST",
      body: JSON.stringify({ city: city })
    })
      .then(r => r.json())
      .then(res => {
        if (res.cod === 404) {
          setError(true);
          setLoading(false);
        }
        return res;
      })
      .then(res => {
        const data = {
          temp: res.main.temp.toFixed(0),
          city: res.name,
          country: res.sys.country,
          weather: res.weather
        };
        setData(data);
        setLoading(false);
        setError(false);
      })
      .catch(err => {
        setError(true);
        setLoading(false);
      });
  }, [city]);
  return { data, error, loading };
};

After we add the custom hooks and Weather component, our project folder structure should look like this:

Step 5

We are pretty much done with the front end. In order for the useFetchWeather custom hook to work, we need to setup the back end. For back end we can take advantage of the Netlify functions. It may seem little confusing how all the pieces of Netlify functions work together. But after you set up your first function, it will be much easier to understand.

First thing is first, let us create the netlify.toml file in then main directory of the project, which will be used by Netlify to figure out where the functions are and how to run them.

// netlify.toml

[build]
	Command = "npm run build"
	Functions = "lambda"
	Publish = "build"

Now open App.js file of your project and add the following code to import the Weather.js file we have just created.

// App.js

import React from 'react';
import Weather from './components/Weather';

const App = () => <Weather/>;

export default App;

Step 6

Inside the /src folder create a new folder named lambda. Navigate to that folder and create the function file inside it – getWeather.js.

Add the following code in to the getWeather.js file

// src/lambda/getWeather.js

import fetch from "node-fetch";
require("dotenv").config();

const API_KEY = process.env.API_KEY; // Store your key in .env file

exports.handler = async (event, context) => {
  const city = JSON.parse(event.body).city;
  const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=imperial&appid=${API_KEY}`;

  console.log(API_KEY);
  return fetch(url, { headers: { "Accept": "application/json" } })
    .then(response => response.json())
    .then(data => ({
      statusCode: 200,
      body: JSON.stringify(data)
    }))
    .catch(error => ({ statusCode: 422, body: String(error) }));
};

As you can see at the top of the function, we have an environment variable which stores the API key for making calls to OpenWeatherMap. To get your own API key, refer here: Get OpenWeatherMap API Key.

Once you get the API key, create a file named .env in the main directory of your project and inside the dotenv file, provide the API key:

API_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXX

Do not forget to add .env name in your .gitignore file. Otherwise your API key will be stored in your remote git repo along with other project files.

Step 7

Before we move on to deploying our app to Netlify, you can run it locally to make sure it is working. In your terminal/command line run npm start to start the app in development mode. You should be able to open localhost:3000 and see the weather app.

Step 8

Next step is it store the project in a remote repository. You can use whatever repository provider you like. I will be storing my project in GitHub.

Once you push the project to a remote repository, we can start the deployment to Netlify. If you do not have an account with Netlify, go ahead and create one!

Step 9

In Netlify:

  • Open the main dashboard and there you should see a big button called New site from Git. Click on that and it will ask you where you want to get project files from. In my case, I select GitHub.
  • Once you authenticate with GitHub (or GitLab/BitBucket), you will see a list of repositories that belong to you. From that list select the Semantic Weather repo and Click Deploy Site
  • Last step is to create an Environment Variable named API_KEY in Netlify. Go to Site settings and click on Environment under Build & Deploy side menu. Then add a new variable and set your OpenWeatherAPI Key as the value.

  • That’s it! It will take couple of minutes for Netlify to fetch your project files and setup the functions. Once it is done, you will see a message saying “Site is live”.
  • If the site is not working, try to trigger deployment manually. It may be having a hard time finding the environment variable.

Link to DEMO | GitHub

Thank you for taking your time to read the article!

Getting Started With React Native

React Native

In this article you will learn how to set up your computer to begin developing apps using React Native.

Before we begin, what is React Native? As stated on the official React Native website, https://facebook.github.io/react-native/, “React Native lets you build mobile apps using only JavaScript. It uses the same design as React, letting you compose a rich mobile UI from declarative components.” The site goes on to say, “With React Native, you don’t build a ‘mobile web app’, an ‘HTML5 app’, or a ‘hybrid app’. You build a real mobile app that’s indistinguishable from an app built using Objective-C or Java. React Native uses the same fundamental UI building blocks as regular iOS and Android apps. You just put those building blocks together using JavaScript and React.”

You can learn more by reading the documentation at https://facebook.github.io/react-native/.

One important thing to keep in mind, is that, although React Native allows you to develop iOS and Android apps, you will need to have a Mac computer to build an iOS application.

Setting Up Your Computer

Depending on your experience, skills and what you plan on doing, you may either want to develop with Expo or with the React Native CLI. What’s the difference?

Expo is the easiest and quickest way to get started and build simple apps. There is no need to use Xcode or Android studio, simply use the Expo CLI to develop your app and run it on your phone using the Expo client app.

React Native CLI, on the other hand, allows more flexibility and control. With it you can do things, such as, using third party packages that require you to run the command “react-native link”. It also allows you to go in and make changes to native iOS and Android code. But the installation process will vary depending on the operating system your computer is running. Window users be aware that you will not be able to build iOS projects because iOS development requires a Mac. On the other hand, Mac using will be able to develop for both iOS and Android.

I will be walking you though, both the Expo and React Native CLI installation. Let’s begin with Expo. If you prefer Reactive Native CLI, please skip ahead to the Reactive Native CLI installation section.

Expo Installation

To use Expo, you need to install Node. The fastest and easiest way to install Node is through the website. Head to https://nodejs.org and choose a version. LTS is more stable, more likely to work, and the recommended option. Current is the latest version of Node but may not work with React Native. Choose one, download it and follow the instructions to install. Node will also install npm. Using the Node website will work for both Mac and Window users.

Once installed you can check the version of Node by opening the Terminal or Command Prompt and type the following and then press the “Enter” key:

node -v

Node will also install npm, to check the version type:

npm -v

If you are unsure how to open Terminal or Command Prompt, here is how to do so:

To open the Terminal on a Mac, open the Applications folder, then the Utilities folder and click on Terminal. Or press “Command” and ‘space” keys to open Spotlight and search for “Terminal”, which will be under “Application” section.

To open the Command Prompt on Windows, search for cmd in the Start menu. Or press the “Windows” and “R” key to open the Run window and search for “cmd”.

Version used in this article:

Node version = v10.15.3 and npm version = 6.9.0

Next install the Expo CLI command line utility. Do so by typing the following into your Terminal or Command Prompt:

npm install -g expo-cli

The next step is not mentioned in the React Native documentation, but the Expo documentation states that you will need Git on your computer to create projects. The link to Expo’s installation documentation is located here, https://docs.expo.io/versions/latest/introduction/installation/.

 

You can download Git here, https://git-scm.com/downloads. Download the correct version for your computer.

Start the Git setup. The Mac and Windows installation process differ. The Windows setup offers much more options than the Mac setup. I am not a Windows user, so I left all the settings as default and installed. You may need to restart your computer afterwards.

 

(Git installation on Windows)

The final step is to install the Expo client app on your phone.

Download the Expo client app for iOS from the App Store, https://itunes.apple.com/app/apple-store/id982107779. Or search for “Expo Client” in the App Store.

Download the Expo client app for Android from the Google Play Store, https://play.google.com/store/apps/details?id=host.exp.exponent&hl=en_US. Or search for “Expo Client” in the Google Play Store.

Having an Expo account will open up a few more options, such as publishing projects to your Expo portfolio. You can create an Expo account through the app or through their website, https://expo.io/. This step is optional.

React Native CLI Installation

React Native CLI has a series of steps that will vary for Mac and Window users. I will start by guiding you through the steps for those using Mac, then for those using Windows.

Mac Installation

Start by installing Homebrew, head to https://brew.sh, copy the script and paste it into the Terminal.

Once installed, run the following command in the Terminal:

brew install node
brew install watchman

Installing Node will also install npm.

Next step is to install the React Native CLI by typing:

npm install -g react-native-cli

iOS Set Up

Let’s first start by downloading Xcode, which is necessary for iOS builds.

You will find Xcode at https://itunes.apple.com/us/app/xcode/id497799835?mt=12, click “View in Mac app store” to download and install. Or open the Mac App Store and search for “Xcode”.

Next, install Xcode Command Line Tools. Open Xcode and choose “Preferences…” from  the Xcode menu on the upper left corner of the screen. The General window will open, go to Locations and toward the bottom, install the Command Line Tools by selecting the latest version from the dropdown.

At this point you are ready to create your first React Native project but if you want to develop for Android too, please follow the following steps.

Android Set up

Let’s focus on downloading what’s needed for Android builds.

First thing to do is install the Java SE Development Kit (JDK). You can find it at http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html.

Next, install Android Studio, you can find it at https://developer.android.com/studio/index.html.

Once installed open Android Studio, the Android Studio Setup Wizard will open. Click “Next” and when asked to choose between “Standard” and “Custom” installation, pick “Custom”.

Click “Next” and choose the theme you would like, then click “Next”. At this point it will ask you to check the components you would like to download. According to the React Native documentation, check Android SDK, Android SDK Platform, Performance (Intel HAXM) and Android Virtual Device.

 

(I had Android Studios already install and that is why I got a warning at the bottom.)

Click “Next” and leave the Emulator settings on the recommended setting and click “Next”, then “Finish”.

There are a couple more steps left.

Open Android Studio and in the lower right side of the window, click Android Studio click on “Configure” and “SDK Manager”.

Select the “SDK Platforms” tab, make sure you have “Show Package Details” checked on the bottom right side of the window. Select Android 9.0 (Pie) and make sure Android SDK Platform 28, Intel x86 Atom_64 System Image and Google APIs Intel x86 Atom System Image are checked.

Then click on the “SDK Tools” tab, making sure “Show Package Details” is checked on the lower right side of the window. Look under “Android SDK Build-Tools 29-rc2”, make sure 28.0.3 is selected.

Now click “Apply”, accept the user agreements and install.

Last step is to add a few lines to your “.bash_profile”. Open up Terminal and type:

nano .bash_profile

Then add the following lines:

export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=$PATH:$ANDROID_HOME/tools
export PATH=$PATH:$ANDROID_HOME/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools

 

To save the changes simply press “Control” and “X”. You will be asked to save changes, hit “Y” and then “Enter” to exit.

You’re all set for iOS and Android development on your Mac.

Windows Installation

Begin by installing Chocolatey, which can be found at  https://chocolatey.org/install/. Copy the command under “Install with cmd.exe” and paste it into the Command Prompt.

 

 

To open the Command Prompt, search for “cmd” in your Start menu, right click on it and select “Run as administrator”. A pop up will open asking for permission, select “Yes”. Copy the command provided into the Command Prompt and install.

Ensure that it is installed by typing:

choco

This will return the version and a command for the help menu.

Then type:

choco install -y nodejs.install python2 jdk8

After that, it is time to install the React Native CLI by typing the following into the Command Prompt:

npm install -g react-native-cli

I noticed that when I tried to do this, I got an error saying “npm” was not a recognized command. Restart your computer, open cmd as an administrator and try again.

Next, install Android Studio. You can find it at https://developer.android.com/studio/index.html. Open Android Studio, the Android Studio Setup Wizard will open. Click “Next” and when asked to choose between “Standard” and “Custom” installation, pick “Custom”.

(This window, and a few of the following, are screenshots taken on a Mac.)

Click “Next” and choose the theme you would like, then click “Next”. At this point it will ask you to check the components you would like to download. According to the React Native documentation, check Android SDK, Android SDK Platform, Performance (Intel HAXM) and Android Virtual Device. Click “Next” and leave the Emulator settings on the recommended setting and click “Next”, then “Finish”.

(Ignore the warning. This image is a screenshot from my Mac and I had previously installed Android Studios.)

Open Android Studio and in the lower right side of the window, click on “Configure” and “SDK Manager”.

Select the “SDK Platforms” tab, make sure you have “Show Package Details” checked on the bottom right side of the window. Select Android 9.0 (Pie) and make sure Android SDK Platform 28, Intel x86 Atom_64 System Image and Google APIs Intel x86 Atom System Image are checked.

Then click on the “SDK Tools” tab, making sure “Show Package Details” is checked on the lower right side of the window. Look under “Android SDK Build-Tools 29-rc2”, make sure 28.0.3 is selected.

 

Next search for “Environment variables” in the Start menu, and select “Edit the system environment variables”. When the window opens, click on the “Advanced” tab and towards the bottom select the “Environment Variables”. Under “User variables for YOUR_USERNAME”, click “New” and add the following:

Variable name = “ANDROID_HOME”
Variable value = “c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk”

You can find the location of the SDK by looking in the “SDK Manager” settings of Android Studio.

 

Next select “Path” in the “User variables for YOUR_USERNAME” and select “Edit”. A new window will open, click “New” and add the following:

c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk\platform-tools

Close the “Edit environment variable”, “Environment Variables” and “System Properties” windows by clicking “Ok”.

You are all set! Let’s begin by creating an Expo project, if you decide to use only React Native, please skip ahead.

Creating Expo Project

From here on out I will be working on a Mac, the steps will be the same on Windows but I will not be using the Command Prompt. I will be using commands, such as “clear”, that will work in the Terminal but may not work in the Command Prompt.

Open up a new Terminal and head to the directory you wish to save the project in.

I like to save my projects onto my Desktop, so I will type:

cd Desktop

Once in the directory of your choice, type:

expo init FirstProject

“expo init” initializes a directory called “FirstExpoProject”. If you prefer to name the project something else, replace “FirstExpoProject” with the name of your choice.

There will be an option given to “Choose a template”, select “Blank” and press “Enter”.

Next, you are prompted to enter “The name of your app visible on your home screen”. I will type “FirstExpoProject” and press “Enter”.

Congrats! You created your first React Native app. To enter the folder type:

cd PROJECT_NAME

And the follow to start it:

expo start

Or

npm start

A new tab will open in your web browser, called the Expo Dev Tool. Depending on your computer this may take some time.

You will have a few options to view the app.

One way to view the app is to use the QR code. In the Terminal and Expo Dev Tool you will see a QR code. You can scan the code with the Expo app on Android or the iPhone’s camera.

Make sure your computer and phone are on the same network when the “Connection” in Expo Dev Tools is set to “LAN”. If you select “Tunnel”, then both devices can be on different networks.

Another way to view the app is to type “e” in the Terminal, allowing you to send an email or text message with a link to the app. You will have the same option in the browser.

And the final option I will discuss, is to open the app in the Android emulator or iOS simulator, which requires you to first install Android Studio and Xcode. If you want to do this, please look at the section titled “React Native CLI”.

Once you have it running it will look like this:

It’s now time to see what we created! You will need a text editor for this part and my personal preference is Visual Studio Code, which can be downloaded here https://code.visualstudio.com/. There are other options, such as Atom and Sublime, for example. Since I will be using Visual Studio Code, some of the following steps may differ if you are using a different editor.

Open Visual Studio Code, and open the “FirstExpoTutorial” project. On the left side of the editor you will see the “Explorer” section. If you do not see it, click on “View” at the top of the screen and then on “Explorer”.

In the “Explorer”, open up App.js file, this is where we will modify the code.

 

The first line of code imports the default export React from the module react.

The second line is importing components from React Native. React Native has a bunch of built in components and apis which you can see here, https://facebook.github.io/react-native/docs/components-and-apis.

Next comes the class App, which has the function render(), that returns JSX code, similar to HTML, and is exported.

The JSX consist of a View, a container that supports layout, and Text, a React component for displaying text. Replace the text between the <Text></Text> tags, with:

<Text>Hello World! Welcome to my new expo app!</Text>

Save the file and the app will reload with the new text.

The last block of code you will notice is the constant named styles. This is the styling that is passed to the View component and is similar to CSS styling.

Creating React Native Project

The steps to create a project using the React Native CLI are similar to Expo. Use the command “cd” to move directories. I will use the following command to move to the Desktop directory, but you can choose any directory:

cd Desktop

Once you are in the directory you wish to create the project in, type :

react-native init FirstRNProject

“react-native init” initializes a directory called “FirstRNProject”. You can choose to name your project something else.

During the initialization it may suggest that you use Yarn to speed it up. This is optional but if you want Yarn you can download it at https://yarnpkg.com/en/docs/install#mac-stable. There is a Homebrew option I will use on Mac, type the following in the terminal:

brew install yarn

In Windows either use the Installer or Chocolatey. To use Chocolatey, type the following into the Command Prompt as an administrator:

choco install yarn

Congrats! You created your first React Native app. Now it’s time to run the app. After creating the project, you may have noticed that there are instructions on how to run it. First thing to do is to enter the project folder by typing the following into the Terminal:

cd FirstRNProject

If you are on a Mac, you can run you iOS project two ways. One is to type the following into the Terminal:

react-native run-ios

This command will start building your app and will open it on the iOS simulator. Second way to run the project is to open the “YOUR_PROJECT_NAME.xcodeproj” file inside the “ios” folder of the React Native project. Xcode will open up, select the simulator and click on the run button at the top left side of the window.

This is how the app will look on the simulator:

If you are using Windows or Mac and want to run the app on Android, start by opening up Android Studios to start up the emulator before running the command in the Terminal.

Select “Open an existing Android Studio project” from the “Welcome to Android Studio” window.

Navigate to the directory where the project is located and the select the “android” folder inside and click “Open”. There may be a popup asking you to update the Android Gradle plugin. Don’t upgrade because it may cause the project not to work, I clicked “Don’t remind me again for this project”.

Before running the command in the Terminal, there is one last thing to do and that is to check the AVD Manager. Go to Tools in the top of the screen and click on “AVD Manager”. The Android Virtual Device Manager window will open. I have a device already set up using Android 9.0.

If you don’t see a device or want to create a new one, click on “Create Virtual Device”. Select the device you want and click “Next”. On the following screen select “Pie”, download if needed” and click “Next”.

Give the device a custom name or leave it as default and click “Finish”. Choose a device to run and click on the green play button under “Actions”.

Once the emulator is running, go back to the Terminal and inside the project you created run the following command:

react-native run-android

Here is how the project will look in the emulator:

It’s now time to see what we created! You will need a text editor for this part and my personal preference is Visual Studio Code, which can be downloaded here https://code.visualstudio.com/. There are other options, such as Atom and Sublime, for example. Since I will be using Visual Studio Code, some of the following steps may differ if you are using a different editor.

Open Visual Studio Code, and open the FirstTutorial project. On the left side of the editor you will see the Explorer section. If you do not see it, click on “View” at the top of the screen and then on “Explorer”.

Since the project was created with the React Native CLI, you will notice that this project has more folders than an Expo project. Two folders that stand out are the Android and iOS folders, which will give you access to native code.

In the Explorer, open up App.js file, this is where we will modify the code.

The first line of code, “import React from ‘react’”, imports the default export React from the module react.

The second line is importing components from React Native. React Native has a bunch of built in components and apis which you can see here, https://facebook.github.io/react-native/docs/components-and-apis.

The React Native project will then have a constant named “instructions”. What it does is determine which kind of phone that app is running on and will display text accordingly.

Next comes the class App, which has the function render(), that returns JSX code, similar to HTML, and is exported.

The JSX consist of a View, a container that supports layout, and a few Text, a React component for displaying text. Delete the bottom two, then replace the text between the <Text></Text> tags, with:

<Text>Hello World! Welcome to my new React Native app!</Text>

Save the file and if the text on the simulator/emulator does not change, simply reload the app. To do so on the iOS simulator press “Command” and “D” and click reload. In the Android emulator press “Command” and “M” if running it on Mac or “Control” and “M” on Windows.

The last block of code you will notice is the constant named styles. This is the styling that is passed to the View component and is similar to CSS styling.

Now What?

Congratulations! You have installed everything necessary to create a React Native project, started the project and modified the code. Take a look at the React Native documentation or Expo documentation and play around with the project. Add more text, change the background color, add an image or a button. This is just the beginning, in no time you will be creating amazing apps and publishing them for the world to see.

What are React Hooks and why you should care about them – Part 2

Outline

  1. Context Hook
  2. Custom Hooks
  3. Important Rules with Hooks
  4. Sample application

In the first part of the blog, we discussed the main concepts of React Hooks and the reasons for using them. We compared the traditional ways of creating components and the new ways with hooks. In the second part, we will continue exploring the the different types of hooks, learn about the important rules and create a sample application. We have a lot to cover. Let’s get started!

Context Hook

What is a context?

First of all, what is a context in React?

Context is a way to share global data across components without passing props. Usually, data in React application is passed from parent to child through props. Sometimes we have some data that should be delivered to a component deep inside the component tree. It is tedious to manually pass the same data over and over again through all components. Instead, we can create a central store that can be inserted into any component, just like in Redux.

How about we see an example code without Context API and identify the need for using it.

Let’s say there is a banana  plantation called “App” and it sets the prices for all bananas in the world. Before bananas reach the end customers, they need to go through wholesalers and supermarkets first. After that we can go to the stores and buy them. But since wholesalers and supermarkets need to add their profit margins in the process, the cost of the bananas go up.

Without Context API

// App.js
import React, { useState } from 'react';

const App = () => {
  const [bananaPrice, setBananaPrice] = useState(2); // Original price: $2
  return <Wholesaler price={bananaPrice}/>;
}

const Wholesaler = (props) => {
  const price = props.price + 2;
  return <Supermarket price={price}/>;
}

const Supermarket = (props) => {
  const price = props.price + 3;
  return <Customer price={price}/>;
}

const Customer = (props) => {
  return (
	<div>
		<p>Plantation price: $2</p>
		<p>Final price: ${props.price} :)</p>
	</div>
  );
}

What if we want to buy the bananas straight from the plantation and avoid the middlemen?

Now, the same code with Context API

With Context API

// App.js
import React, { useState } from 'react';

// First we need to create a Context
const BananaContext = React.createContext();

// Second we need to create a Provider Component
const BananaProvider = (props) => {
  const [bananaPrice, setBananaPrice] = useState(2); // Original price: $2
  return (
    <BananaContext.Provider value={bananaPrice}>
      {props.children}
    </BananaContext.Provider>
  );
}

const App = () => {
  return ( // Wrap the component in Provider, just like in Redux
    <BananaProvider>
      <Wholesaler/>
    </BananaProvider>
  );
}

const Wholesaler = () => {
  return <Supermarket/>;
}

const Supermarket = () => {
  return <Customer/>;
}

const Customer = () => {
  return (
    <BananaContext.Consumer>
      {(context) => (
        <div>
          <p>Plantation price: $2</p>
          <p>Final price: ${context} 😃</p>
        </div>
      )}
    </BananaContext.Consumer>
  );
}

useContext()

So how can we use Context API with hooks? With useContext!

import React, { useState, useContext } from 'react';

// First we need to create a Context
const BananaContext = React.createContext();

// Then we need to a Provider Component
const BananaProvider = (props) => {
  const [bananaPrice, setBananaPrice] = useState(2); // Original price: $2
  return (
    <BananaContext.Provider value={bananaPrice}>
      {props.children}
    </BananaContext.Provider>
  );
}

const App = () => {
  return ( // Wrap the component in Provider, just like in Redux
    <BananaProvider>
      <Wholesaler/>
    </BananaProvider>
  );
}

const Wholesaler = () => {
  return <Supermarket/>;
}

const Supermarket = () => {
  return <Customer/>;
}

const Customer = () => {
  const context = useContext(BananaContext);
  return (
    <div>
      <p>Plantation price: $2</p>
      <p>Final price: ${context} :)</p>
    </div>
  );
}

I know you could remove the line where you add the price to the cost of the banana and still get $2 at the end. But that is not the point. The point is that you have to do the props drilling when you don’t use Context. Incrementing the price while passing the the components is sort of the cost to do the props drilling.

Custom Hooks

Why?

Why would we want to create our own hooks? Because of 1 reason – it makes component logic more reusable.

  • Custom hook = Reusable logic

How?

How do we create a custom hook? Since hooks are just JavaScript functions, we can create a custom hook by just making a function.

  • The only difference is that the function name must start with the word – use. For example, useFunctionNameuseHungerStatus etc.
  • Custom hooks can call other hooks

Example without custom hook

Say we want to create an application with multiple Stopwatch timers on a single page. How would we do that?

This is what I mean by multiple timers:

Here is the code that implements hooks but does not reuse the logic for the timers

import React, { useEffect, useState } from 'react';

const App = () => {
  const [timerOneStatus, setTimerOneStatus] = useState(false);
  const [timerOneElapsed, setTimerOneElapsed] = useState(0);

  const [timerTwoStatus, setTimerTwoStatus] = useState(false);
  const [timerTwoElapsed, setTimerTwoElapsed] = useState(0);

  useEffect(() => {
    let intervalOne;
    if (timerOneStatus) {
      intervalOne = setInterval(
        () => setTimerOneElapsed(prevTimerOneElapsed => prevTimerOneElapsed + 0.1),
        100
      );
    }
    return () => clearInterval(intervalOne);
  }, [timerOneStatus]);

  useEffect(() => {
    let intervalTwo;
    if (timerTwoStatus) {
      intervalTwo = setInterval(
        () => setTimerTwoElapsed(prevtimerTwoElapsed => prevtimerTwoElapsed + 0.1),
        100
      );
    }
    return () => clearInterval(intervalTwo);
   }, [timerTwoStatus]);

  const handleReset1 = () => {
    setTimerOneStatus(false);
    setTimerOneElapsed(0);
  };

  const handleReset2 = () => {
    setTimerTwoStatus(false);
    setTimerTwoElapsed(0);
  };

  return (
    <div>
      <div>
        <h2>Stopwatch 1</h2>
        <h1>{timerOneElapsed.toFixed(1)} s</h1>
        <button onClick={() => setTimerOneStatus(!timerOneStatus)}>
          {timerOneStatus ? "Stop" : "Start"}</button>
        <button onClick={handleReset1}>Reset</button>
      </div>
      <div>
        <h2>Stopwatch 2</h2>
        <h1>{timerTwoElapsed.toFixed(1)} s</h1>
        <button onClick={() => setTimerTwoStatus(!timerTwoStatus)}>
          {timerTwoStatus ? "Stop" : "Start"}</button>
        <button onClick={handleReset2}>Reset</button>
      </div>
    </div>
  );
}

As we can see, we are not DRY coding here. Logic for the timers need to repeated every time we want to create a new timer. Imagine if we had 10 timers on one page.

Example with custom hook

Now what we could do is to separate the timer logic as a custom hook and use that one hook for creating any number of timers. Each timer would have its own state and action items. In the main component we use the custom hook just like useState or useEffect and destructure returned parameters from the hook.

import React, { useEffect, useState } from 'react';

const App = () => {
  const [timerOneStatus, setTimerOneStatus, timerOneElapsed, resetTimerOne] = useTimer();
  const [timerTwoStatus, setTimerTwoStatus, timerTwoElapsed, resetTimerTwo] = useTimer();

  return (
    <div>
      <div>
        <h2>Stopwatch 1</h2>
        <h1>{timerOneElapsed.toFixed(1)} s</h1>
        <button onClick={() => setTimerOneStatus(!timerOneStatus)}>
          {timerOneStatus ? "Stop" : "Start"}</button>
        <button onClick={() => resetTimerOne()}>Reset</button>
      </div>
      <div>
        <h2>Stopwatch 2</h2>
        <h1>{timerTwoElapsed.toFixed(1)} s</h1>
        <button onClick={() => setTimerTwoStatus(!timerTwoStatus)}>
          {timerTwoStatus ? "Stop" : "Start"}</button>
        <button onClick={() => resetTimerTwo()}>Reset</button>
      </div>
    </div>
  );
}

const useTimer = () => {
  const [status, setStatus] = useState(false);
  const [elapsedTime, setElapsedTime] = useState(0);

  useEffect(() => {
      let interval;
      if (status) {
        interval = setInterval(() =>
          setElapsedTime(prevElapsedTime => prevElapsedTime + 0.1),
          100
        );
      }
      return () => clearInterval(interval);
    },[status]);

  const handleReset = () => {
    setStatus(false);
    setElapsedTime(0);
  };

  return [status, setStatus, elapsedTime, handleReset];
}

In this case, we can place the hook in another file with other custom hooks and call it from anywhere in our project. Much cleaner and more reusable!

Rules with Hooks

Even though hooks are just functions, react team recommends to follow certain rules when using them. If you are lazy or just want to make sure you are following the rules automagically, you can install this linter. However, it is important that we have some common knowledge about the rules.

Rule 1 – Call hooks only at the top level

What does that mean?

It means we should not call hooks inside conditions, loops or nested functions. Rather use them at the top level of React functions.

Rule 2 – Hooks cannot be called from regular JavaScript functions. Call them from React functions

You can call hooks from the following functions:

  • Custom hooks
  • React function components

Rule 3 – Always start your custom hooks’ name with the word ‘use’

Sample application

Now let us build an application that takes advantage of the most hooks we have covered so far.

We will be building an application called Caturday and it will fetch pictures of random cats on the internet and allow us to vote on the pictures. It will keep count of our likes and dislikes. We will also add a button that can turn our page into dark mode (just change the background color of the page for simplicity).

Here is what the final result will look like: Link to Demo | Github

Step 1

We start building our app by running

$ create-react-app caturday

(If you don’t have create-react-app module installed, please run npx create-react-app caturday)

After navigating into the project folder, run

$ npm install semantic-ui-react --save

to install the Semantic UI design tool that will make dealing with CSS much easier.

Step 2

Create 3 files in the /src folder:

  • Caturday.js,
  • Caturday.css
  • customHooks.js

Step 3

Open the Caturday.css file and copy paste the following:

@media only screen and (max-width: 600px) {
  #image-container {
    width: 100%;
    padding-top: 50px;
  }
}
@media only screen and (min-width: 600px) {
  #image-container {
    width: 50%;
    margin: auto;
    padding-top: 50px;
  }
}
.dark-mode {
  background-color: #3b3939;
}
.main-img {
  margin: auto;
  height: 30em !important;
}
.main-placeholder {
  height: 30em !important;
}

Step 5

We create 2 custom hooks to use in our application. Open customHooks.js file and add these hooks

import { useState, useEffect } from "react";

export const useFetchImage = (url, likeCount, mehCount) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    setLoading(true);
    fetch(url)
      .then(j => j.json())
      .then(data => {
        console.log(JSON.stringify(data))
        setData(data);
        setLoading(false);
      })
      .catch(err => {
        console.log(err);
      });
  }, [likeCount, mehCount]);
  return { data, loading };
};

export const useDarkMode = () => {
  const [enabled, setEnabled] = useState(false);
  useEffect(
    () => {
      enabled
        ? document.body.classList.add("dark-mode")
        : document.body.classList.remove("dark-mode");
    },
    [enabled] // Only re-runs when 'enabled' changes
  );
  return [enabled, setEnabled]; // Return state and setter
};

Step 5

We start constructing the primary file Caturday.js by importing the css file and creating a container for the app. We will also define the state of component and a customs hooks that update the image url when Like/Dislike buttons are clicked.

import React, { useState, useEffect } from "react";
import { Header, Segment, Image, Placeholder, Button, Container, Label, Icon, Checkbox } from "semantic-ui-react";
import './Caturday.css';

const Caturday = () => {
  const [likeCount, setLikeCount] = useState(0);
  const [mehCount, setMehCount] = useState(0);
  const [darkMode, setDarkMode] = useDarkMode();
  const {data, loading} = useFetchImage(
    "https://api.thecatapi.com/v1/images/search",
    likeCount,
    mehCount
  );
  
  return (
	<Container id="main-container">
      <Segment raised>
        // Header
        // Dark Mode toggle
        // Image container
        // Like and Dislike buttons
      </Segment>
    </Container>
  );
};

export default Caturday;

Step 6

Now when we define each element of our Caturday component and put all pieces together, our Caturday.js file should look like this.

import React, { useState, useEffect } from "react";
import { Header, Segment, Image, Placeholder, Button, Container, Label, Icon, Checkbox } from "semantic-ui-react";
import './Caturday.css';
import {useDarkMode, useFetchImage} from './customHooks';

const Caturday = () => {
  const [likeCount, setLikeCount] = useState(0);
  const [mehCount, setMehCount] = useState(0);

  const [darkMode, setDarkMode] = useDarkMode();
  const { data, loading } = useFetchImage(
    "https://api.thecatapi.com/v1/images/search",
    likeCount,
    mehCount
  );

  return (
    <Container id="image-container">
      <Segment raised>
      <Header className="ui basic segment centered">Caturday</Header>
        <Segment>
          <Checkbox onChange={() => setDarkMode(!darkMode)} toggle floated='right' label="Dark mode"/>
        </Segment>
        {
          loading ?
          <Placeholder fluid><Placeholder.Image className="main-placeholder"/></Placeholder> :
          <Image src={data[0] ? data[0].url : ''} className="main-img"/>
        }
        <Segment textAlign="center">
          <Button as="div" labelPosition="right">
            <Button onClick={() => setLikeCount(likeCount+1)} icon color="green">
              <Icon name="heart" />
              Like
            </Button>
            <Label as="a" basic pointing="left">
              {likeCount}
            </Label>
          </Button>
          <Button as="div" labelPosition="left">
            <Label as="a" basic pointing="right">
              {mehCount}
            </Label>
            <Button onClick={() => setMehCount(mehCount+1)} color="red" icon>
              <Icon name="thumbs down" />
              Meh
            </Button>
          </Button>
        </Segment>
      </Segment>
    </Container>
  );
};

export default Caturday;

Step 7

Open the App.js file and replace the return content with Caturday component

import React from 'react';
import Caturday from './Caturday';

const App = () => {
	return (
      <Caturday/>
    );
}

export default App;

Conclusion

We have covered most of the concepts about hooks and that should be enough for you to get started. If you have a project that you are working on right now that implements states and components in a traditional way, it is absolutely fine. No need to convert everything into hooks. However, when you are about to create new components, just give the hooks a try. They are 100% compatible with regular components with classes. You will be surprised how many lines of code you will be avoiding to accomplish the same functionalities. If you need more information about hooks, please checkout the official documentation by Facebook.

Thanks for spending your time to read the article!

What are React Hooks and why you should care about them – Part 1

Outline

  1. Intro
  2. What is wrong with React Components now?
  3. Hooks overview
  4. useState
  5. useEffect
  6. TLDR

Intro

There is a new kid on the block . React introduced a new feature called Hooks which will improve the code quality even more and make creating user interfaces easier. From now on, if you are going to create a new project, you should definitely take advantage of the new addition and keep your projects lean and clean. It was actually released a while ago, but production ready stable version has come out recently. So now is the time to really start using them. In this article, we will cover the main concepts and look at some examples. At the end of the article, you will have a fair amount of idea about React Hooks and you can start implementing them in your applications.

Before we dive in to the details of hooks, let us take a step back to understand the motivation behind it.


What is wrong with React components now?

3 things:

  1. Classes
  2. Hierarchical abyss (Not reusing stateful logic)
  3. Big components

1. Classes

Currently, there are mainly two ways to create components in React. First way is by using stateless functions:

function Greet(props){
	return <h1>Hello there, {props.name}!</h1>;
}

Second, using ES6 Classes:

class Greet extends React.Component {
	render(){
		return <h1>Hello there, {props.name}!</h1>;
	}
}

Right, so why are you saying there is something wrong with those two methods, you ask?

Well, first of all, there are no classes in JavaScript. A class is a syntactical sugar over JavaScript’s prototype-based inheritance. In other words, it is just a function with special features, which creates extra work for browser to process. But that is not the problem here. The problem is, classes are harder to understand and do not play well with minifying. They cause issues with hot reloading. Also, people often struggle when deciding to use classes or functions to make the components. Which results in inconsistency.

So, why not to use just functions then? Functions are stateless. Meaning, we cannot manage state in them. We can pass props back and forth, but that makes it hard to keep track of the changes.

2. Hierarchical Abyss

Just take a look at the picture below.

Extreme level of nested component tree makes it difficult to follow the data flow through the app.

3. Big components

Whether we like it or not, at some point of the development, our application gets large and requires more complex components. When that happens, our components end up implementing multiple React lifecycles that might contain unrelated data. A single task can be split across different lifecycles. That creates an opportunity for bugs in the application.


Hooks to the rescue!

Hooks solve all of the issues mentioned above. It does that by allowing us to add state management to functional components and use other React features.

Say what?

See, it is usually preferred to use just functions to create components. But as we mentioned above, we cannot manage the state or use lifecycles in our functions. But with the hooks we can!

(If you are thinking, why not use Redux for state management, hold on to that thought. That’s a discussion for another time.)

State Hook

Let’s look at an example code that changes a text when we click a button.

import React, { useState } from 'react';

function FruitMaster(){
	const [fruit, setFruit] = useState('Banana');
	return (
		<div>
			<p>Selected:{fruit}</p>
			<button onClick={
				() => setFruit(fruit=='Banana'?'Apple':'Banana')
			}>Change</button>
		</div>
	);
}

This is what supposed to happen:

We have a selected text variable, which is set to Banana by default. When we click on the Change button it changes the text from Banana to Apple or vice versa.

Now, let us break down the new elements in the component.

What are those things in the state variable?

In this case, setFruit() is equivalent of this.setState(). There is one important difference though. When we use this.setState(), it merges the changes to the state object. State hook on the other hand, will completely replace the state with the given value.

We used a state hook called useState in this example. There are other hooks too. We will see them soon.

So a hook, is actually a function that uses React features and returns a pair of values: one to hold the state value and one function to manage the value. We can name those values whatever we want. We can set a default value by passing it to the useState function.

Note that we are using a destructuring assignment to retrieve the pair of values. If you are not familiar with this method, take a look at here. Having said that, we could actually get the two values this way too:

const stateVariable = useState('Cherry'); //Returns an array with 2 values
const fruit = stateVariable[0];
const setFruit = stateVariable[1]; //function

Converting

Now, let’s convert our functional component to a class based component:

import React from 'react';

export default class FruitMaster extends React.Component {
  constructor(props){
    super(props);
    this.state = {
      fruit: 'Banana'
    };
    this.setFruit = this.setFruit.bind(this);
  }

  setFruit(value){
    this.setState({fruit: value});
  }

  render(){
    return (
      <div>
        <p>Selected: {this.state.fruit}</p>
        <button onClick={
          () => this.setFruit(this.state.fruit == 'Banana' ? 'Apple' : 'Banana')
          }>Change</button>
      </div>
    );
  }
}

Comparison

We can see from the picture that using hooks reduces code volume almost by half!

Now, let us address the elephant in the room. What do we do when we have more than one variable in state?*

Simple! Create more state variables.

const [fruit, setFruit] = useState('Banana');
const [food, setFood] = useState('Taco');

Multiple state variables

import React, { useState } from 'react';

function FruitMaster(){
	const [fruit, setFruit] = useState('Banana');
	const [food, setFood] = useState('Taco');
	return (
		<div>
			<p>Fruit: {fruit}</p>
			<p>Lunch: {food}</p>
			<button onClick={
				() => setFruit(fruit=='Banana'?'Apple':'Banana')
			}>Change Fruit</button>
			<button onClick={
				() => setFood(food=='Taco'?'Burger':'Taco')
			}>Change Lunch</button>
		</div>
	);
}

What if I want to store all variables in one object? you might ask. Well, go ahead. But one thing to remember is that, state hook function replaces the stateand not merges to it. this.setState() merges the given values to the state object, hook function does not. But there is a way to fix it. Let us see how:

import React, { useState } from 'react';

function MealMaster(){
	  const [myState, replaceState] = useState({
	    fruit: 'Apple',
	    food: 'Taco'
	  });
	  return (
	    <div>
	      <p>Fruit: {myState.fruit}</p>
	      <p>Lunch: {myState.food}</p>
	      <button onClick={
	        () => replaceState(myState => ({
	          ...myState,
	          fruit: myState.fruit=='Banana'?'Apple':'Banana'
	        }))
	      }>Change Fruit</button>
	      <button onClick={
	        () => replaceState(myState => ({
	          ...myState,
	          food: myState.food=='Taco'?'Burger':'Taco'
	        }))
	      }>Change Lunch</button>
	    </div>
	 );
}

We have to use spread operator to change the only part of the state we need and keep the rest of it as it is.

Effect Hook

What about the lifeCycle methods of React? We could use those with classes. But now they are gone…

Not really.

There is another hook called useEffect and we can use it instead of the lifecycles. In other words, we can handle side effects in our applications with hooks. (What is a side effect?)

Here is an example of a component that uses familiar lifecycles:

Old method

import React from 'react';

class TitleMaster extends React.Component {
	constructor(props){
		super(props);
		this.state = {
			title: 'Tuna'
		};
	}
	componentDidMount(){
		document.title = this.state.title; // Changes tab title
	}
	componentDidUpdate(){
		document.title = this.state.title;
	}
	updateTitle(value){
		this.setState({title: value});
	}
	
	render(){
		return (
			<div>
		        <button onClick={
		          () => this.updateTitle(this.state.title =='Tuna'?'Donut':'Tuna')
		        }>Update Title</button>
		    </div>
		);
	}
}

Our component in action.

The component is bulky even for a small functionality. Code in componentDidMount and componentDidUpdate is repeated.

With hooks

Now let’s create the same component with hooks!

import React, { useState, useEffect } from 'react';

function TitleMaster(){
  const [title, updateTitle] = useState('Tuna');
  useEffect(() => {
    document.title = title;
  });
  return (
      <div>
          <button onClick={
            () => updateTitle(title =='Tuna'?'Donut':'Tuna')
          }>Update Title</button>
      </div>
    );
}

export default TitleMaster;

Much cleaner. Less code. Easier to understand.

As we mentioned before, a hook is a function. useEffect is also a function that accepts another function and an array. Don’t worry about the array part for now.

So inside the function we pass to useEffect, we can perform our side effect logic. In the example above, we are updating the tab title in the browser. Another common practice is to use data fetching in the useEffect hooks.

We can also use multiple useEffect hooks in one component.

Note that we are placing the hooks inside of our component functions. That way they will have access to the state variables.

Infinite loop

By default useEffect re-renders every time the component changes. Sometime incorrectly implementing the hook might cause infinite loop issue. Remember, we said that the useEffect takes 2 arguments? So the second argument is an object or array of values. Which tells React, “Hey React, re-run the useEffect only when these state values change

const [user, setUser] = userState();
useEffect(() => {
	document.title = user.id;
}, [user.id]); // Re-render the hook Only when user.id changes

Cleanup logic

useEffect hook can also handle cleanup logic. What does that mean? Well, sometimes we subscribe to some APIs and once we are done, we need to unsubscribe from it to prevent any leaks. Or when we create an eventListener, we need a way to remove it.

useEffect can do it by returning a function.

import React, { useState, useEffect } from 'react';

function TitleMaster(){
  const [title, updateTitle] = useState('Tuna');
  useEffect(() => {
    document.title = title;
    return () => {
		// Perform clean up logic here
	}
  });
  return (
      <div>
          <button onClick={
            () => updateTitle(title =='Tuna'?'Donut':'Tuna')
          }>Update Title</button>
      </div>
    );
}

TLDR:

React hooks are special functions that can be used in stateless components. They allow us to hook into react features and add state management to the components. There are 3 main hooks: useState, useEffect and useContextuseState can replaces the current way of declaring state object in the constructor and manipulating values in it by using this.setState()useEffect can be used instead of react lifecycles. These hooks are not meant to replace the current way of creating components. They are backwards compatible. No need to rewrite your existing components using hooks. They can make your projects much cleaner by letting you write less code though.

Part 2: What are React Hooks and why you should care about them

In Part 2 we will cover the following:

  • Context Hook
  • How to make custom hooks!
  • Important Rules with Hooks
  • Real life application example