# React Hooks

5 min read, 867 words reacthooksrouter

Born as an RFC in November 2018 they caught up quickly and landed in React 16.8.

Inject your code into react lifycycle using hooks provided by react.

  • Share logic between components

# useState

# useEffect

imitation of ComponentDidMount

  const [data, setData] = useState("Click me, please");

  useEffect(() => {
    fetch("http://localhost:3001/links/")
      .then(response => response.json())
      .then(data => setData(data));
      .catch(error => console.log(error))
  }, []);  // => that is, variables on which useEffect depends on to re-run.
Close websocker connection after opened in useEffect

return a function to clean up the effect, that is, a function which runs when the component unmounts.

cleanup after component is removed, unmounted

useEffect(() => {
    const socket = socketIOClient(ENDPOINT);
    socket.on("FromAPI", data => {
    setResponse(data);
    });

    return () => socket.disconnect();
}, []);

# custom Hook

  • Persist input value in local storage and backend server
How to reuse component logic using customHooks?

try this

import { useState, useEffect } from "react";

export default function useFetch(url) {
const [data, setData] = useState([]);

useEffect(() => {
    fetch(url)
    .then(response => response.json())
    .then(data => setData(data));
}, []);

return data;
}

const data = useFetch("http://localhost:3001/links/");

asyn/await with useEffect

Turns out you cannot return a Promise from useEffect.

This wont work! Console will scream

import { useState, useEffect } from "react";

export default function useFetch(url) {
  const [data, setData] = useState([]);

  useEffect(async () => {
    const response = await fetch(url);
    const data = await response.json();
    setData(data);
  }, []);

  return data;
}
Usinf async/await with useEffect?

use This

import { useState, useEffect } from "react";

export default function useFetch(url) {
const [data, setData] = useState([]);

async function getData() {
    const response = await fetch(url);
    const data = await response.json();
    setData(data);
}

useEffect(() => {
    getData();
}, []);

return data;
}

# useReducer

dispatch action strings as best practise

  • complex state changes in React components.
  • These actions end up in a reducer function to calculate the next state:
  • Reducer function takes a state and action
  • Action might havr a type and payload

spread operator in react reducer

# Use clases

  • Calculator webapp
  • Custom add-Ons (which increases the price) on a product buy page
  • reduced sum of nested arrays

# useContext

How to broadcast variables (theme, viewport-sizes, padding-margins) implicitly to all enclosed components?

Accepts a context object (the value returned from React.createContext) and returns the current context value for that context

  • Which components can access global store data? Provide to components?
  • Basic setup, writing to use useContext?

# Best Practises

  1. Use context sparingly
  2. Prefer HoC or react component composition | containment strategies alongwith IOC
  3. Multiple level of prop-drilling ? prefer props as JSX Functions, render props
  4. Because context uses reference identity to determine when to re-render, there are some gotchas that could trigger unintentional renders in consumers when a provider’s parent re-renders. Because new object are always created for context values.
    1. to solve, lift up the value to component states

# useCallback and useMemo

useCallback(fn, deps) is equivalent to useMemo(() => fn, deps).

# useRef

  • The returned object will persist for the full lifetime of the component.
  • set via .current property of Element

# use case

  1. To access the DOM: <div ref={myRef} />
  2. Store mutable value like instance variable (in class)
  3. A render counter
  4. A value to be used in setTimeout / setInterval without a stale closure issue.
const FancyButton = React.forwardRef((props, ref) => (
  <button ref={ref} className="FancyButton">
    {props.children}
  </button>
));

// You can now get a ref directly to the DOM button:
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;

# useMemo

  • Returns a memoized value.
  • Pass a “create” function and an array of dependencies
  • useMemo will only recompute the memoized value when one of the dependencies has changed. This optimization helps to avoid expensive calculations on every render.
  • Remember that the function passed to useMemo runs during rendering

# useLayoutEffect

The signature is identical to useEffect, but it fires synchronously after all DOM mutations. Use this to read layout from the DOM and synchronously re-render.

# useDebugValue

useDebugValue can be used to display a label for custom hooks in React DevTools.

# react-router-dom

Make Bookmarkable app states

  • Make router available to the parts of app that would need it.
  • How to add new route? and render new components?
  • Link, Route, Switch exact to only 1 component from list, path="/g/:gistId"
    • then app finds and filters gistId from the available collection
  • Can use slots, this.props.children pattern or pass as props
  • Common pitfalls (opens new window)

# Exercises

Subscribe to our Newsletter

If you like my work and think it was helpful kindly support my work


Buy Me A Coffee