Custom Hooks and Sockets
Tags: hooks, showdev, react, node
Published: 2019-09-10 18:04:56

---
title: Custom Hooks and Sockets
published: true
description: implementation of hooks and socket to stream live data
tags: hooks, showdev, react, node
---

So, it's been a while since the hooks came in and I've been trying to find time to try and learn to create custom hooks. Really mind-boggling 🧠. Though the interesting part is that the concept may be simple but if you find the right use case to it. 

The first thing i wanted to try out was to make network request and to see how we can implement using hooks. The usual way in react was obviously  **setState**. Assuming that most of you have worked with setState. Now let's see how to write it in a functional component using **Hooks**.	

For this let's use JSON placeholder to fetch posts.

```jsx
import React,{ useState } from "react";

// URL to fetch posts
const postsUrl = "https://jsonplaceholder.typicode.com/posts"

// Our Component
const ListPosts = () => {
	// Using state hook to set if loading
	const [ loading, setLoading ] = useState(true);
	// Fetch and set list of posts
	const [ posts, setPosts ] = useState([]);

	//Here we fetch the posts and add it to posts state
	fetch(postsUrl)
		.then(res => res.json())
		.then(data => { setPosts(data); setLoading(false); })
		.catch(err => {
			alert('Error fetching posts');
			setLoading(false);
		});

	//Our Component which will lists posts
	return(
		<div>
			// Loop through the list of posts
			<h1>My Posts <span>{posts.length}</span></h1>
			{loading ? 
				<h1>Loading posts...</h2> 
				: posts.map(post => (
					<div>
						<h3>{post.title}</h3>
						<hr/>
						<p>{post.body}</p>
					</div>
			})}
		</div>
	)
}
```
In this component we used **useState** hook to set posts and loading state. But now let's see how we can rewrite this as a hook separating the logic from component. 

First let's use the effect hook which will react to changes inside the component. Let's check it out.

```jsx
React.useEffect(() => {
	// Function called whenever something updates in component
},[ /* Update based on variable */ ])
```

Now let's see how to use it in our component
```jsx
import React,{ useState } from "react";

// URL to fetch posts
const postsUrl = "https://jsonplaceholder.typicode.com/posts"

// Our Component
const ListPosts = () => {
	// Using state hook to set if loading
	const [ loading, setLoading ] = useState(true);
	// Fetch and set list of posts
	const [ posts, setPosts ] = useState([]);

	// Use effect to update component
	React.useEffect(() => {
		//Here we fetch the posts and add it to posts state
		fetch(postsUrl)
			.then(res => res.json())
			.then(data => { setPosts(data); setLoading(false); })
			.catch(err => {
				alert('Error fetching posts');
				setLoading(false);
			});
	},[ postsUrl ])

	//Our Component which will lists posts
	return(
		<div>
			// Loop through the list of posts
			<h1>My Posts <span>{posts.length}</span></h1>
			{loading ? 
				<h1>Loading posts...</h2> 
				: posts.map(post => (
					<div>
						<h3>{post.title}</h3>
						<hr/>
						<p>{post.body}</p>
					</div>
			})}
		</div>
	)
}
```

Now let's separate the logic from the application

```jsx
// Here is our hook which makes request and returns the posts
const usePosts = (postUrl) => {
	const [ loading, setLoading ] = useState(true);
	const [ posts, setPosts ] = useState([]);
	
	React.useEffect(() => {
		//Here we fetch the posts and add it to posts state
		fetch(postsUrl)
			.then(res => res.json())
			.then(data => { setPosts(data); setLoading(false); })
			.catch(err => {
				alert('Error fetching posts');
				setLoading(false);
			});
	},[ postsUrl ])
	
	return { loading, posts }
}

// Adding it to our component
const postsUrl = "https://jsonplaceholder.typicode.com/posts";

const ListPosts = () => {
	const { loading, posts } = usePosts(postsUrl);
	
	return(  
		<div>  // Loop through the list of posts  
			<h1>My Posts <span>{posts.length}</span></h1>  
			{loading ?  
				<h1>Loading posts...</h2>
				: posts.map(post =>  (
				<div>
					<h3>{post.title}</h3>  
					<hr/>
					<p>{post.body}</p>
				</div>
				})}  
		</div>)
}
```

So there we go, we have created our first simple custom hook. This is okay if we are going to use static requests to fetch data. What if we are going to recieve a stream of data based on events.
Let's see how we can write the same component using a socket to fetch temperature from an IoT Device. Which will constantly send data.

For this I've created a sample code that streams a random temperature between 0 and 100 using express and socket-io. The code is as below.

```jsx
// server.js
const app = require('express')();
const server = require('http').createServer(app);
const socket = require('socket.io');
const io = socket(server);

const port = 8080 || process.env.PORT;

io.on('connection', () => {
    console.info('SOME ONE IS HERE');
});

setInterval(() => {
    const temp = Math.floor(Math.random()* 100);
    const topic = 'temperature';
    console.info(`TEMP : ${temp}`);
    io.emit(topic,temp);
}, 3000);

const listenCb = () => console.table([['status', 'port'],['started',port]])
server.listen(port, listenCb);
```
Install the dependencies and run the server using the follwoing code

```sh
npm i -S socket.io express

# Run the app using nodejs
node app.js
```

This will constantly send the data every 3 seconds.

Now let's see how to use this in our React's component using custom hooks. First let's write our hook.

```jsx
import React from 'react';
import PropTypes from 'prop-types';
import socket from 'socket.io-client';

// Use socket to fetch request to data 
// Socket server's url and topic in which data is sent
const useSocket = (serverUrl, topic) => {
    const [temp, setTemp] = React.useState(0);
    const [isConnected, setConnected] = React.useState(false);

    React.useEffect(() => {
        const client = socket.connect(serverUrl);
        client.on("connect", () => setConnected(true));
        client.on("disconnect", () => setConnected(false));
        client.on(topic, (data) => {
            setTemp(data);
        })
    }, [serverUrl, topic, isConnected]);

    return { temp, isConnected };
}

// Our component which sends the request through the topic
const Sockt = () => {
	const serverUrl='http://localhost:8080', topic='temperature';
    const { temp, isConnected } = useSocket(serverUrl, topic);

    return (
        <div>
            <h4>Temperature</h4>
            <h1>{temp}</h1>
            <h3>{`CONNECTED: ${isConnected}`}</h3>
        </div>
    )
}
```

The component now will show the temperature which is received from the socket server. Every time data is sent through the socket.

I hope, you got to learn something new and interesting. Find the code sandbox for the implementation of what we went through this entire article.

Backend - Socket Server 🧦
https://codesandbox.io/s/express-socket-io-70t5x

React using hooks
https://codesandbox.io/s/priceless-greider-3b814