React Hooks by Example - Part 1
Tags: react, webdev, hooks, javascript
Published: 2023-02-04 20:58:34

## Learn Hooks = Make Money!🤑

Let's jump right in!
Oh wait, what are hooks?

[React docs](https://reactjs.org/docs/hooks-intro.html) has this to say
> "Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class"

Honestly though, you're definitely better off learning hooks there, but in case you prefer a less bloated source in more of a go-to, no-BS spirit, read on!
Okay let's make some money!

The code for all the examples can be found at this [Code Sandbox](https://codesandbox.io/s/u2tbtz).
This is Part 1 of a three-part series, and it covers the OG hooks; **useState**, **useEffect** and **useContext**!😎

---
## useState
- The `useState` hook is used to store and update dynamic data in the application, i.e. "State".
- Create a state variable and a function to update said state value:
    ```
    const [state, setState] = useState(initialState);
    ```
- Update the value of the state variable:
    ```
    setState(newState);
    ``` 
- Example:
    ```javascript
    // /src/UseStateExample.js 

    import { useState } from "react";

    export default function UseStateExample() {
      const [counter, setCounter] = useState(0);

      return (
        <div className="UseStateExample">
          <h1>Dinero!</h1>
          <h2>You have {counter} 💵</h2>
          <button onClick={() => setCounter(counter + 1)}>Get 1 $</button>
        </div>
      );
    }
    ```
- In the above example, 
  - The state variable `counter` is initialized to 0 using the `useState` hook. 
  - When the button is clicked, the setter function `setCounter` runs and increments the value of `counter` by 1.
- See it in action [here](https://u2tbtz.csb.app/use-state) and the code at this [sandbox](https://codesandbox.io/s/react-hooks-examples-u2tbtz?file=/src/UseStateExample.js)!

---
## useEffect
- The `useEffect` hook takes a callback function and an optional dependency array, as arguments.
- It is used to run some logic inside a callback function, when the value of any of the variables in a specified dependency array changes.
- If the dependency array is empty, then the function runs once when the component is initialy loaded.
- If you need to run some logic before the component is unmounted, this can be done by **returning** a function from the callback to `useEffect`.
- Example:
    ```javascript
    // /src/UseEffectExample.js

    import { useEffect, useState } from "react";

    export default function UseEffectExample() {
      const [counter, setCounter] = useState(0);

      useEffect(() => {
        if (counter >= 1000000) {
          alert("Congratulations! You're a Millionaire");
        }
      }, [counter]);

      return (
        <div className="UseEffectExample">
          <h1>Dinero!</h1>
          <h2>You have {counter} 💵</h2>
          <button onClick={() => setCounter(1000000)}>Become a Millionaire!</button>
        </div>
      );
    }
    ```
- In the above example:
  - The callback to `useEffect` will run each time the value of `counter` changes.
  - When `counter >= 1000000`, an alert will be displayed! 
- See it in action [here](https://u2tbtz.csb.app/use-effect) and the code at this [sandbox](https://codesandbox.io/s/react-hooks-examples-u2tbtz?file=/src/UseEffectExample.js)! 

---
## useContext
- React's *Context API* allows you to share data between components without having to prop-drill them down the hierarchy, i.e. without having to pass data down to each child component. The `useContext` hook allows us to do this.
- We can create a Context in the top-level component like so:
    ```
    const CashContext = createContext("one million dollars");
    ```
- And we can wrap the child components inside a Provider, and they will have access to the value:
    ```
    function App(props) {
      return (
        <CashContext.Provider value={"one million dollars"}>
          <ChildComponent1 />
        </CashContext.Provider>
      );
    }
    ```
- We can then use the `useContext` hook inside nth level child components to access this value passed to the Provider:
    ```
    function ChildComponent1(props) {
      return (
        <div>
          <ChildComponent2 />
        </div>
      );
    }

    function ChildComponent2() {
      const cash = useContext(CashContext);

      return (
        <div>{cash}</div>
      );
    }
    ```
- Note: the below example illustrates how Context can be used to access **and update** values from within child components, which is a pretty useful pattern.
- Example:
    ```javascript
    // /src/context/emojiContext.js

    import { createContext } from "react";

    export const emojis = {
      "heavy-dollar-sign": "💲",
      "dollar-banknote": "💵",
      "money-bag": "💰"
    };

    export const EmojiContext = createContext({
      emoji: emojis["heavy-dollar-sign"],
      setEmoji: () => {}
    });
    
    // --------------------------------------------------------
    // /src/App.js

    import "./styles.css";
    import { useState } from "react";
    import { BrowserRouter, Routes, Route } from "react-router-dom";
    import { emojis, EmojiContext } from "./context/emojiContext";
    import UseContextExample from "./UseContextExample";

    export default function App() {
      const [emoji, setEmoji] = useState(emojis["heavy-dollar-sign"]);
      const emojiValue = { emoji, setEmoji };

      return (
        <div className="App">
          <EmojiContext.Provider value={emojiValue}>
            <BrowserRouter>
              <Routes>
                <Route path="use-context" element={<UseContextExample />} />
              </Routes>
            </BrowserRouter>
          </EmojiContext.Provider>
        </div>
      );
    }

    // --------------------------------------------------------
    // /src/UseContextExample.js

    import { emojis, EmojiContext } from "./context/emojiContext";
    import { useContext } from "react";

    export default function UseContextExample() {
      const { emoji, setEmoji } = useContext(EmojiContext);

      const getRandom = () => {
        if (emoji === emojis["heavy-dollar-sign"]) {
          return emojis["money-bag"];
        } else {
          return emojis["heavy-dollar-sign"];
        }
      };

      return (
        <>
          <h1>Dinero!</h1>
          <h2>You have {emoji}</h2>
          <button onClick={() => setEmoji(getRandom())}>
            Click to get something else
          </button>
        </>
      );
    }
    ```
- In the above example:
  - We create a Context in `emojiContext.js` and export it.
  - Import it into `App.js` and wrap the child components inside the Provider.
  - The "value" passed to the Provider are the state variable and setter function.
  - In `UseContextExample.js` we use the `useContext` hook to access and update the value as needed.
- See it in action [here](https://u2tbtz.csb.app/use-context) and the code at this sandbox for [emojiContext.js](https://codesandbox.io/s/react-hooks-examples-u2tbtz?file=/src/context/emojiContext.js), [App.js](https://codesandbox.io/s/react-hooks-examples-u2tbtz?file=/src/App.js) and [UseContextExample.js](https://codesandbox.io/s/react-hooks-examples-u2tbtz?file=/src/UseContextExample.js)! 

Hope this was fun and you're sleeping on stacks of cash by now!
Stay tuned for Part 2 and 3 where we look at more hooks🤘
Cheers!