Aquasar
  • Home
  • Portfolio
  • Articles
  • Pricing
  • About
  • Contact
WEB DEVELOPMENT |SEO |DIGITAL ADS

React Hooks Intro

Jun 28th, 2019

Alex Quasar

reactreact hooksreact hooks intro

React Hooks are a new feature of React that let you do things without classes. This new way of thinking about React definitely encourages a more functional way of programming.

Hooks: useState

The useState hook is used to update the state of your application. Here is a simple example to get started.

import React, { useState } from 'react';

import './App.css';

function App() {
  const [count,setCount] = useState(0);
  const [fruit, setFruit] = useState('Bananas');

  const myFruits = ['Apple','Stawberry','Peach', 'Bananas','Watermelon','Kiwi','Papaya','Blueberry'];


  return (
    <div className="App">
       <p> You have clicked me { count } times </p>
       <p> The selected fruit is: { fruit } </p>
       <button onClick = { () => setCount(count + 1) } > Click Me </button>
       <button onClick = { () => setFruit( myFruits   [Math.floor(Math.random()*myFruits.length ) ] ) } > Random Fruit </button>
    </div>
  );
}

export default App;

Above, useState is a react hook that allows as to return two things. The current state value and the function that updates this value. We can have multiple useState hooks in each function. The first useState returns count and setCount with an inital state of 0. The initial state can be any data type.

A popular way of handling events is to use event handlers. With event handlers we define a new function rather than put the logic inside the onClick event. For example:

function App() {
  const [count,setCount] = useState(0);

  const buttonCountHandler = () => {
    setCount(prevCount => prevCount + 1);
  }


  return (
    <div className="App">
       <p> You have clicked me { count } times </p>
       <p> The selected fruit is: { fruit } </p>
       <button onClick = { buttonCountHandler } > Click Me </button>
    </div>
  );
}

export default App;

Here we also used prevCount which is like prevState but specific to count inside of useState. Doing it this way is cleaner in my opinion because you don't have all the logic of the function in the return statement. For the fruits we can simply update it using:

  const updateFruitHandler = () => {
    const myFruits = ['Apple','Stawberry','Peach', 'Bananas','Watermelon','Kiwi','Papaya','Blueberry'];
    setFruit( myFruits[Math.floor(Math.random()*myFruits.length ) ] ) 
  }

and inside the return adding:

 <button onClick = { updateFruitHandler } > new random Fruit </button>

The Light Switch Example

import React, { useState } from 'react';

import './App.css';

function App() {

  const [isOn, setIsOn] = useState(false);

  const toggleLightHandler = () => {
    setIsOn( prevIsOn => !prevIsOn );
  }


  return (
    <div className="App">

        <h2>Toggle a light</h2>
        <div 
            style = {{
              width: '10rem',
              height: '10rem',
              background: isOn ? 'yellow' : 'black' ,
              margin: 'auto'
            }}
        />

        <button
           style = {{cursor:'pointer'}} 
           onClick = {toggleLightHandler}
        > 
          {isOn ? 'Turn Off': 'Turn On'}
        </button>

    </div>
  );
}

export default App;

Hook: useEffect

Fetching data or interacting with any sort of API. Use effect replaces the component life cycles methods.

In this example we can use useEffect to replace componentDidMount and componentDidUpdate lifecycles.

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

useEffect( () => {
    document.title = `The light is turned ${ isOn ? 'on' : 'off' } `;
 })

Example Mouse Positioning

To track mouse positions, we reach out to the window API. The useEffect hook allow us to update mouse coordinates. Events like these required us to use componentDidMount and componentWillUnmount lifecycles methods. With Hooks in we can do the following:

import './App.css';

function App() {

  const [mousePosition,setMousePosition] = useState( { x: null, y: null } );

  const setMousePositionHandler = event => {
      setMousePosition( { x: event.x, y: event.y } );
  }

  useEffect( () => {
    window.addEventListener('mousemove',setMousePositionHandler)

    return () => {
      window.removeEventListener('mousemove',setMousePositionHandler)
    }
  },[] )


  return (
    <div className="App">
    <h2>Mouse Position</h2>
    <p>The mouse coordinates x and y are { `${mousePosition.x} and ${mousePosition.y}` }  </p>
    </div>
  );
}

export default App;

To only run on mount and unmount we pass the following empty array argument inside of useEffect. We can unmount the event listener by returning the window.removeEventListener.

Online or not?

Using useEffect and navigator api to determine whether we are online or not.

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

import './App.css';

function App() {


  const [ status, setStatus ] = useState( navigator.onLine );

  const onlineEventHandler = () => {
    setStatus(true);
  }

  const offlineEventHandler = () => {
    setStatus(false);
  }

  useEffect( () => {
    window.addEventListener('online', onlineEventHandler);
    window.addEventListener('offline', offlineEventHandler);

    return () => {
      window.removeEventListener('online', onlineEventHandler);
      window.removeEventListener('offline', offlineEventHandler);
    }
  },[] )


  return (
    <div className="App">
    <h2> Online or not?</h2>
    <p> You are now: { status ? 'Online' : 'Offline' } </p>
    </div>
  );
}

export default App;

Geolocation Example

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

import './App.css';

const initLocationState = {
  latitude: null,
  longitude:null,
  speed:null
}


function App() {

  let mounted = true; // lets us mount and unmount after use
  // es6 desctructuring on location
  const [ {latitude,longitude,speed} , setLocation ] = useState( initLocationState );
  
  const geoLocationHandler = event => {
    if (mounted) {
      setLocation({
        latitude: event.coords.latitude,
        longitude: event.coords.longitude,
        speed: event.coords.speed
      })
    }
  }

  useEffect( () => {

    navigator.geolocation.getCurrentPosition(geoLocationHandler);
    // update the geolocation
    const watchId = navigator.geolocation.watchPosition(geoLocationHandler);


    return () => {
      // remove event listeners.
      mounted = false;
      navigator.geolocation.clearWatch(watchId);
    }
  },[] )


  return (
    <div className="App">
    <h2> Geolocation </h2>
    <p>Latitude: { latitude }</p>
    <p>Longitude: { longitude }</p>
    <p>Speed: { speed ? speed: '0' }</p>
    </div>
  );
}

export default App;

Simple Form with Hooks

Doing a simple login form with Hooks takes quite a lot of code up front. Here is a bare bones basis form

import React, { useState } from 'react'

const Login = (  ) => {

    const [username, setUsername] = useState("");
    const [password, setPassword] = useState("");

  
    const handleSubmit = event => {
      event.preventDefault();
      const userData = {
        username,
        password
      };
      
      // form submit logic goes here.
      console.log(userData);
      // reset the form after
      setUsername("");
      setPassword("");
    };


    return (
        <div>
        <h2>Simple Form</h2>
        <form

          onSubmit={handleSubmit}
        >
          <input
            type="text"
            placeholder="Username"
            onChange={event => setUsername(event.target.value)}
            value={username}
          />
          <input
            type="password"
            placeholder="Password"
            onChange={event => setPassword(event.target.value)}
            value={password}
          />
          <button type="submit">Submit</button>
        </form>
  
    
      </div>
    )
}

export default Login

Simple API Requests with Hooks

import React, { useState, useEffect } from 'react';
import './App.scss'
import axios from 'axios';

function App() {
  const [results, setResults] = useState([]) // set results to empty array
  const [query, setQuery] = useState('react hooks');

  try {
      useEffect(() => {
        const fetchData = async () => {
        const results = await axios(
          `http://hn.algolia.com/api/v1/search?query=${query}`,
        );

      // setstate of results to results array.
        setResults(results.data.hits);
        console.log(results.data.hits);
      };

      fetchData();

    }, [query]); // only run on componentDidMount and componentUnmount and query state change
        
  } catch (error) {
      console.log(error)
  }

  const setQueryHandler = e => {
      setQuery(e.target.value);
  }

  return (
      <div className="App">
     
          <h4> Search Top 20 Results from API: </h4>
          <input onChange = { setQueryHandler } type="text"/><br/>
        {
            results.map(result => (
              <div key = {result.objectID}> {result.title} </div>
            ))
          }
      </div>
  
  );
}

export default App;

Simple API with form and useRef Hook

In this example we create a function getResults to set the state of the results from the query API. We call this function side useEffect so it runs on the initial page load. We also create a searchEventHandler to only make calls to API on a form submission ( button search click or enter key )

import React, { useState, useEffect, useRef } from 'react';
import './App.scss'
import axios from 'axios';

function App() {
  const [results, setResults] = useState([]) // set results to empty array
  const [query, setQuery] = useState('react hooks');
  const searchInputRef = useRef();

  // load search on componentDidMount, componentDidUpdate
  useEffect( () => {
    getResults();
  },[]);

  const getResults = async () => {
    try {
      const response = await axios.get(`http://hn.algolia.com/api/v1/search?query=${query}`);
      setResults(response.data.hits);

    } catch (error) {
        console.log(error);
    }
  }

  const searchEventHandler = e => {
    console.log("search submit");
    e.preventDefault();
    getResults();
  }

  const setQueryHandler = e => {
      setQuery(e.target.value)
  }

  const clearSearchHandler = () => {
    setQuery('');
    searchInputRef.current.focus(); // put focus back into input handler.

  }

  return (
      <div className="App">
     
          <h4> Search Top 20 Results from API: </h4>
          <form onSubmit = { searchEventHandler }>
            <input 
              type="text"
              value = { query }
              onChange = { setQueryHandler }
              ref = { searchInputRef }
            />

            <br/>
            <button type = "submit"> Search </button>
            <button onClick = { clearSearchHandler } type = "button"> Clear </button>
          </form>
         

          {
            results.map(result => (
              <div key = {result.objectID}> {result.title} </div>
            ))
          }
      </div>
  
  );
}

export default App;

See github for source code:

https://github.com/arhoy/react-hooks-intro