React Hooks


Hook : it allows you to have "state"in "fuctional components"--> fuctional programming!
** Before you start, you need to import below first.
import React, { useEffect, useState, useRef } from "react";
import ReactDOM from "react-dom";
** Tip! Below two have the same fuction.
fuction APP() {}
const APP = () => {};
  • useState: first factor is value ((ex)’item’ below) and the other is modifying value((ex) ‘setItem’ below). And it returns Array.
  • const App = () => {
      const [item, setItem] = useState(1);
      const incrementItem = () => setItem(item + 1);
      const decrementItem = () => setItem(item - 1);
      return (
        <div className="App">
          <h1>Hello {item}</h1>
          <button onClick={incrementItem}>Increment</button>
          <button onClick={decrementItem}>Decrement</button>
        </div>
      );
    };
    1-1. useInput
    const useInput = (initialValue, validator) => {
      const [value, setValue] = useState(initialValue);
      const onChange = event => {
        const {
          target: { value }
        } = event;
        let willUpdate = true;
        if (typeof validator === "function") {
          willUpdate = validator(value);
        }
        if (willUpdate) {
          setValue(value);
        }    
      };
      return { value, onChange };
    };
    
    const App = () => {
      const maxLen = (value) => value.length <= 10; 
      const name = useInput("Mr. ", maxLen);
      return (
        <div className="App">
          <h1>Hello</h1>
          <input placeholder="Name" {...name}/>
        </div>
      );
    };
    
    
    1-2. useTabs
    const content = [
      {
        tab: "Section 1",
        content: "I'm the content of the Section 1"
      },
      {
        tab: "Section 2",
        content: "I'm the content of the Section 2"
      }
    ];
    
    const useTabs = (initialTab, allTabs) => {
      if (!allTabs || !Array.isArray(allTabs)) {
        return;
      }
      const [currentIndex, setCurrentIndex] = useState(initialTab);
      return {
        currentItem: allTabs[currentIndex],
        changeItem: setCurrentIndex
      };
    };
    
    const App = () => {
      const { currentItem, changeItem } = useTabs(0, content);
      return (
        <div className="App">
          {content.map((section, index) => (
            <button onClick={() => changeItem(index)}>{section.tab}</button>
          ))}
          <div>{currentItem.content}</div>
        </div>
      );
    };
  • useEffect:
  • componentDidMount + componentWillUnMount + componentDidUpdate, if you do
    useEffect(sayHello); That will watch every changes.
  • componentDidMount only and no update, if you do
    useEffect(sayHello, []);
  • componentDidUpdate only, if you do
    useEffect(sayHello, [number]); That will call sayHello fucntion only when number is updated. dependency([ ]) is very important!
  • const App = () => {
      const sayHello = () => console.log("hello");
      const [number, setNumber] = useState(0);
      const [aNumber, setAnumber] = useState(0);
      useEffect(sayHello, [number]);  
      return (
        <div className="App">
          <div>Hi</div>
          <button onClick={() => setNumber(number + 1)}>{number}</button>
          <button onClick={() => setAnumber(aNumber + 1)}>{aNumber}</button>
        </div>
      );
    };
    
    2-1. useTitle : to update your document title
    const useTitle = (initialTitle) => {
      const [title, setTitle] = useState(initialTitle);
      const updateTitle = () => {
        const htmlTitle = document.querySelector("title");
        htmlTitle.innerText = title;
      };
      useEffect(updateTitle, [title]);
      return setTitle;
    };
    
    const App = () => {
      const titleUpdater = useTitle("Loading...");
      setTimeout(() => titleUpdater("Home"), 3000);
      return (
        <div className="App">
          <div>Hi</div>
        </div>
      );
    };
    
    2-2. useClick
    When component mount, we add EventListener (it's gonna be forever as we didn't add any dependency([])), and it returns a fuction that will be working as componentWillUnMount which is removing the EventListener.
    const useClick = (onClick) => {
      if (typeof onClick !== "function") {
        return;
      }
      const element = useRef();
      useEffect(() => {
        if (element.current) {
          element.current.addEventListener("click", onClick);
        }
        return () => {
          if (element.current) {
            element.current.removeEventListener("click", onClick);
          }
        };
      }, []);
      return element;
    };
    
    const App = () => {
      const sayHello = () => console.log("say hello");
      const title = useClick(sayHello);
      return (
        <div className="App">
          <h1 ref={title}>Hi</h1>
        </div>
      );
    };
    2-3. useHover
    const useHover = onHover => {
      if (typeof onHover !== "function") {
        return;
      }
      const element = useRef();
      useEffect(() => {
        if (element.current) {
          element.current.addEventListener("mouseenter", onHover);
        }
        return () => {
          if (element.current) {
            element.current.removeEventListener("mouseenter", onHover);
          }
        };
      }, []);
      return element;
    };
    2-4. useConfirm
    const useConfirm = (message = "", onConfirm, onCancel) => {
      if (!onConfirm || typeof onConfirm !== "function") {
        return;
      }
      if (onCancel && typeof onCancel !== "function") {
        return;
      }
      const confirmAction = () => {
        if (window.confirm(message)) {
          onConfirm();
        } else {
          onCancel();
        }
      };
      return confirmAction;
    };
    
    const App = () => {
      const deleteWorld = () => console.log("Deleting the world...");
      const abort = () => console.log("Aborted");
      const confirmDelete = useConfirm("Are you sure", deleteWorld, abort);
      return (
        <div className="App">
          <button onClick={confirmDelete}>Delete the world</button>
        </div>
      );
    };
    
    2-5. usePreventLeave : when users try to leave the page, it pops up the warning message saying "changes you made may not be saved".
    const usePreventLeave = () => {
      const listener = (event) => {
        event.preventDefault();
        event.returnValue = "";
      };
      const enablePrevent = () => window.addEventListener("beforeunload", listener);
      const disablePrevent = () =>
        window.removeEventListener("beforeunload", listener);
      return { enablePrevent, disablePrevent };
    };
    
    const App = () => {
      const { enablePrevent, disablePrevent } = usePreventLeave();
      return (
        <div className="App">
          <button onClick={enablePrevent}>Protect</button>
          <button onClick={disablePrevent}>Unprotect</button>
        </div>
      );
    };
    2-6. useBeforeLeave
    const useBeforeLeave = (onBefore) => {
      if (typeof onBefore !== "function") {
        return;
      }
      const handle = (event) => {
        const { clientY } = event;
        if (clientY <= 0) {
          onBefore();
        }
      };
      useEffect(() => {
        document.addEventListener("mouseleave", handle);
        return () => document.removeEventListener("mouseleave", handle);
      }, []);
    };
    
    const App = () => {
      const begForLife = () => console.log("pls dont leave");
      useBeforeLeave(begForLife);
      return (
        <div className="App">
          <h1>Hello</h1>
        </div>
      );
    };
    
    2-7. useFadeIn
    const useFadeIn = (duration = 1, delay = 0) => {
      if (typeof duration !== "number" || typeof delay !== "number") {
        return;
      }
      const element = useRef();
      useEffect(() => {
        if (element.current) {
          const { current } = element;
          current.style.transition = `opacity ${duration}s ease-in-out ${delay}s`;
          current.style.opacity = 1;
        }
      }, []);
      return { ref: element, style: { opacity: 0 } };
    };
    
    const App = () => {
      const fadeInH1 = useFadeIn(1, 2);
      const fadeInp = useFadeIn(5, 10);
      return (
        <div className="App">
          <h1 {...fadeInH1}>Hello</h1>
          <p {...fadeInp}>lalalalala</p>
        </div>
      );
    };
    2-8. useNetwork: It's going to detect when navigator goes online or offline
    const useNetwork = (onChange) => {
      const [status, setStatus] = useState(navigator.onLine);
      const handleChange = () => {
        if (typeof onChange === "function") {
          onChange(navigator.onLine);
        }
        setStatus(navigator.onLine);
      };
      useEffect(() => {
        window.addEventListener("online", handleChange);
        window.addEventListener("offline", handleChange);
        () => {
          window.removeEventListener("online", handleChange);
          window.removeEventListener("offline", handleChange);
        };
      }, []);
      return status;
    };
    
    const App = () => {
      const handleNetworkChange = (online) => {
        console.log(online? "We just went online" : "We are offline")
      }
      const onLine = useNetwork(handleNetworkChange);
      return (
        <div className="App">
          <h1>{onLine ? "Online" : "Offline"}</h1>
        </div>
      );
    };
    
    
    2-9. useScroll
    const useScroll = () => {
      const [state, setState] = useState({
        x: 0,
        y: 0
      });
      const onScroll = () => {
        setState({y: window.scrollY, x: window.scrollX});
      };
      useEffect(() => {
        window.addEventListener("scroll", onScroll);
        return () => window.removeEventListener("scroll", onScroll);
      }, []);
      return state;
    };
    
    const App = () => {
      const { y } = useScroll();
      return (
        <div className="App" style={{ height: "1000vh" }}>
          <h1 style={{ position: "fixed", color: y > 100 ? "red" : "blue" }}>Hi</h1>
        </div>
      );
    };
    2-10. useFullscreen
    const useFullscreen = (callback) => {
      const element = useRef();
      const runCb = (isFull) => {
        if (callback && typeof callback === "function") {
          callback(isFull);
        }
      };
      const triggerFull = () => {
        if (element.current) {
          if (element.current.requestFullscreen) {
            element.current.requestFullscreen();
          } else if (element.current.mozRequestFullScreen) {
            element.current.mozRequestFullScreen();
          } else if (element.current.webkitRequestFullscreen) {
            element.current.webkitRequestFullscreen();
          } else if (element.current.msRequestFullscreen) {
            element.current.msRequestFullscreen();
          }
          runCb(true);
        }
      };
      const exitFull = () => {
        document.exitFullscreen();
        if (document.exitFullscreen) {
          document.exitFullscreen();
        } else if (document.mozCancelFullscreen) {
          document.mozCancelFullscreen();
        } else if (document.webkitExitFullscreen) {
          document.webkitExitFullscreen();
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen();
        }
        runCb(false);
      };
      return { element, triggerFull, exitFull };
    };
    
    const App = () => {
      const onFullS = (isFull) => {
        console.log(isFull ? "We are full" : "We are small");
      };
      const { element, triggerFull, exitFull } = useFullscreen(onFullS);
      return (
        <div className="App" style={{ height: "1000vh" }}>
          <div ref={element}>
            <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAoHCBYWFRgSFRUYGBUYGBgYGBgZGBgYGBgaGRgaGhgYGBgcIS4lHB4rIRgYJjgmKy8xNTU1GiQ7QDs0Py40NTEBDAwMEA8QHhISHDEhISM6NDExMTQ0NDE0NDQxNDQ0NDQ0NDQxNDQ0NDQ0NDQ0NDQ0MTQ0MTQ0NDE0MTE0MTE0NP/AABEIAMcA/gMBIgACEQEDEQH/xAAcAAABBQEBAQAAAAAAAAAAAAACAAEDBAYFBwj/xAA8EAACAQIEAwUFBwQCAQUAAAABAgADEQQSITFBUWEFInGBkQYTFTKhQlJUk7HB0RRi0vAj4XIWM1OCsv/EABgBAQEBAQEAAAAAAAAAAAAAAAABAgME/8QAHxEBAQEBAAICAwEAAAAAAAAAAAERAhIhMUEDIlET/9oADAMBAAIRAxEAPwCWPeADHmwV494JMbNAO8V4GaODAKPBvFeAV494wjwHvHEQEJRGhCPaPkjhY0MBCBhKkQSAhCAiCQhAa0VoRiEKZVhMY0ZpUCxgQorQgYSrHCwwJQlWTrRPKPQok6yyGsfCBJRw4AuZbTLsLSnUctJsMnSFSrvpHLQiLHSOUkGGEe8ciCRICWPaADDQwFlgGT2gskCINCDRMkCESgwxIVMkUwJlhqZEphqIVIJIogIJIIUaiNljRXgEwggRrx4BRrRxHIgAYMIiNKhrRwIhCAhDWiEe0ICBLSqEbQs0BRJaVK5F5VGoM6GGYDTjIqFK5sNpeWkL34yKECPaS2gkQjzz3kfPILxXmcTU2aSK0rBoQaU1aDx7ysGhhoVIxg2jXhCQILCURCPAkUyRTIBJFMKmBhAyINCBhUmaK8GPBgrxXg2jwYMGPmgCKDBExiYrQgkaYBgbG2/C+14SE97NYAEWPPQanzMlVITIDoRpofQ3H1AlTACGogHS5YgDS3Thr5yVBKmJqVMmWBTtaGjgWtvbeDVfhx/SZ22t5JHRoAEd39JPklHAG27Hrylk45L5frwEWpgiIrQHxi3sNeskZuojTHnBoGAaRndw+UDUa85WqpreVPGOWqSQU5dVBHNIQYp+7hLTlzLHyyGKgpGLIZcyxysLikFhBZZKRCnIYgAhhZOKYGpIA6kD9YsOVcsovdTY32PhGmIlSSqksLRkwoQqqKcWSX1pRzSEg55EG0uvh5Eaci4gyxwJOKccUY0xCIQkwpR/diXTALHtC92I+XpNamBkZNicq3J1OthoLDU6X20hmmLAW0FrDgLbQrRqYmFXS0A1DIgLf7eOIhU4raWEhNSMxg3mipQ+nWTU362lZRyhFTwEgpbcYNxAJjGQGQI6gGCIdJbmwFydgIUmSCBO1huywbe9fKPujVvM8J1FwtOnqtIMD9od+/mbzOpaydoarNioVhrRFuqSq+Fwx3XL/wCLEfTaNNZxUkmUTv1uyEBAVXYHUEMLeZ4TjdoY2kgKKlnUkEszEaaaSeSs9juxndxUNduPdygBRfQLr147zvYHssopyo7ZtWax19BoPCc/G9lOaqOz2pFFd2v3FW9zc8zynXwOLd3NZstKgrCy7MVA7oAGxbe0mgcnAj1kiJOkmPp1Veq7AU1J1a1wfurbXl6zmL2kjOEp07rcC5OYm53I4eUaDZIyiW8bUoBsobI1r23H8xUMIzrmSzDpp+sa0gMiKSd0K6EEHrAIjVxFljFZLaCRJq+KIiLLJMsWWPI8UVoxEmFOEKUulitaJpZKCCUllZxVyxESYrBZZrUxARBkrLBCS6mHSTNWPOR5IiOUDm5YMnCR2pzPkuIkUnQbnSd/CVcNRXKzgv8AabUeQNtv1maxuJ92O6CXI0sCbDnpxmWxnadRXBZSOWYbzNrNeoVaiOpNOp53DDwM4I7cqUmKh7EGxG49Ji8L2m6VA6nun51GxHTXhNJTehXF73biR3X9OMlpI72C9sXDAVACn3h83jaSduWZf6im3cIBIG2v2h9LzC9sYd6JzKcyE2vxB5NLXZ/awGFqo50vlUXvqw2+l41caL2f7Tc1QudiioxIuco2HhuZwMXijWrtbUO5t1udPpHxFT3GFJGj1MoY8e9wB4WF/Wc72ce7tUOyDKD1bc+g+sn0v27nbfbF6lPBAZaalAXDWb5dgNhuNZR7SxSoBhUVgEcsWJ7zMwFnLDS1pncbi/eVHfW9yR4A2X6WnXwOJXEj3dWwqqtlf7wHBhxIikdX2gxBREw6m6ooYm+rNc2v9T5xhXfCUhXNi7WGU3trc5RbbTcym+Oz1UpuozghGI+VtdCPX6y12733WmeQA5XY7/7ymNbkUuy+0nxFQlxcE3dtdOg4cLCdnG+07IP6fDnbRiD8gH2QR9ZxcQxQDB0R32uC3EDYknmbEybA9kJhyK1Z9VPdUbMR03Y/SL0TlufZ01qmHJrgA3umupH/AHrpLXuJmuxPaL3lYBlZVAZluDlsoubnYmbYUtFYbMAfWNWenO9zG93OqmCJ4iH8OPMS+zyn9cf3cb3c6/w/+4Q/ho5xlPPlxfdxvdztHs/lCTs4cT6S5UvXLhmjBNGaX+kXlHGGQaZRNSVnyjMf05PCOMGx4GadaYGwAiZRGVPOfxlhhCdLQv6A7nQTR5FHASGpY6ZRJtWWX6Zh6dpD7s8pqRQXkt4QoryHpL5UuMahElAEgQSZRLhrN9ue0KI7Ue9dTY2Atf16zh/E6b6E36MP2ln2uSnTr5nS/vFD3sNSO6db9B6zKVXpk6Ky+cjNdp8Dc3psCPuk6+R/mU2LoQWDIQbqdvMHjKdDGMh7r3HIi07eGxyVlKNy1B/UGPg9Vewfavv0am4uw3/uG1+hmbxIyOad9Fb15H0j4aqadUa7MVPUbf8Acm7aHfDDiPqP9EZ7Pp2e3q4alvqHGX0sT5Ayp2ZUKUHYb94+gsPrIcTWvS0FzlUE8gbE26kn6RUrDDHmQ3/64yfS/aDss2Dsde7b13/SNRrWIqKbEG46W4eEbDGyN1J/SV0NhpzhGg7Uq5gmJXfQHy1HoQR6S72jWOaliBqpy5rdDmH7+k53ZLB0aieIuv72+hlugpVGoOL2vbqDqCPAzl1cd+ZqTGOf6k1EP2L+mn8Sk1VnK1KnezMxIv8AZFgqAcrnzk2HoEtm3IAH7ehtbzkzYcDKCbKCDcC/cYjN5gX9JzvbrOD0qrOyU0dixfW+gRdiBy0v6Cen+zvaYqaEdy+Sn1CLqeuw9Z53gcMQzsfmUe7B5sbr56X18JquyK4pkMdEpD3aD7znRj+pjnv2z3xsbsHkPOJzpGosCARxAPrDYT0/Tx/aupsZZBlcjjHzmSdY1ZqYmNeRe+6QTWE15J41OYJMgNWAakeS+NWCYDtK7VZE1TrJ5L4rDRiZVatANeRcWs0Yt0+sptipGcXLgzlNpapESmgMnQmW1HP9ruy0q0PeZbtSu+2uW3fA9Abf2zzF1pk6d0ec9lGuh1B0I5jlPL+3uzqdGq1PaxuASb5W1X+PKSUvtxPdpewaSIFQ5g+o2A4+cCqiX0JP++ESBN736GbZM+Y988Tf95ex75lB5H9ZBnL6bIN47nOdNFWZVYpqTQPjf0P/AGZNhz/wlej/ALx8PYpk45besLCVAEyEa2I9SZm1ucq1FTk9Y1ChmW3Gdn2d9n6uJZ6aFVyAMS9wO8bACwOpsfSQYbCsjshFmVipB5g2I+kz11jXPOrXYfZbVKiKLjvoDbQgFgCR5T0XtT2Ou4qUSMuxRja22oPETg+zmHBrUy1NgcyHMCdwwtfpPUwZniTuXyX8nV4sxxML7O0VVFZFYqpU3A1JYMT6gzl9vex6uM9CyMAe6T3WvvqdQfpNhGvOl/HzZmOM/J1LuszjfZtMqul1dApIGoaygEkfe0Bv0mdagUdQbPbWmv2STqzv5/pPRyZiDXVnek9rq7hGI0+Y2G+vDxnD83PMyx3/AA99XZWr7NrZqanMGPFhtJ2aU+z2yIqtlHVRZT/BlsmdefiONn7UxkTuBa5tc2HUnhHr1goLMQAJmcd2+WcKqkIpNybgtw04W1vJ11I6c83r4aNzIyZnsL7QW0c3txtY+dun6GdRO0KbbONeB8AbH1Es6lLzYtF4DPBbnImhCdzzkLPzjPInvNQp3qyP3sjczmV+1qSmxcXvbQE28SNJr0z7dOrilUEsbATi4rtk3sEsOBbQnyMoY72hTZAG55gR6CcCvj2Y3J5842fRjWpiV6/SWExC85lBi/7pOmLvu5nPWvFrFrrzmZ9ucCj0xiN2p2U23KM37E38zGSsPvGGzqQQToeBEeR4vPGYfZW3jAvrsJ1e2MGVchMoQ6jhvuPWc6pTCm183UbTpK5V1uyuw6+IXMirkBy6uqAm1+O45zU4f2CY2D4mmo4hFLHyJIlj2YUJhkFgpIJIvfUk7nnO2lTqJz669uvPPpne3fY1KNIVqNViyEZ8xXVToCLDSxt5HpM/Tw/vNrLUXcbZuonomIph0emTo6svqLXnntJO8KbtkqA2SpwNjbK3nM7a1Jj0b2CwjJRdnXK7PblcIot9SZk+3aQGMrjQ3cts9+8A32fGbTsMOtJFq2zi9yNiL906dLTFe07WxdQXsDkOr5R8i+sxZsxvn51ofZCn/wA69youUM2vyaC29uZm/DzE+yK6M/QDSrnG9/lt3dhNF7zqZeb4xnr9q6vvIjW6zlhzGLzflWfCOn78cxPNHxJes5XObu9igDfaNu7uZtKtUKrOdlBY+AF/2nn3s4nvKy3F9cxuC1tbm5BBHRtuc5971jp+POdr03A0siqATfKM3U21JHA+EnvOfntHGKIllxiz7cPF4XE1HcMjFc5ykkAZbnLY+FtoFLsOoVIbKhtYXNxw5ec0BxF9wJGxU/ZEnjF8rJjB47BVKRAYXGuo1HzKNxuveB65bHjKAxBBtfTujqb5mdvG4A9J6JXoowKkaEEHzmE7ewIovbdTqDbccQQOQB9BNzlPKjw/btRNS2hKk8rZ6asfIOfK0ZPaqsMis1iXam+xsyqLW2+Y6icTEOCpHO/ncWYb63HgNBoLa8utWNmubkhGv/fTbLm81Impyze2rHtbVNrhiz/IigFzY2ZnNrILg6AH6SCr7XVFOVyc52Snkdh/5ubgHoomeqVO85DFS9QqWG60wuZgOVyTKqv/APGQg/sUvU011O4P03m5yze2pftWpW7rrURDx0I/+1gNPKS1cFTt3Kh1tcFreI9eMyakAEldbEg1KjZzpwRf3mt7Hwxq0EqfeB+hK/tM2Y1Otc6phUvoWAvrsdOhB1gDDJxY24WBv5id/wCF87QD2SeGsaWMkG6xCsb7nhOYuI6yVaomcsXXSSow+1J0qNbe/hrOYtVdL/rLNPGKOMqB7W1VWKg2a3e03HDXpKGMQ5EYhBuMqWuBwZwDx/aTY3F50y/3X2vz3v4yI1P+MppuDpfccbm3hxnSfDn18th7P4hfcIBbiO7ca3N9DqTOyjjhMH2Z2iyqFB2ubFiSegvt4TuUu1Gy3/acuubrrzZY1CFuBEw+JdXqu1Ozguxam2l9dSh67+cHH9rPUBUsyDNdbMcpsLWLDcX1kOAoF2vUAYD7YYhtORHHxlnOe6l625Hovs849wmUPl71g/zL3j3T0GoHQCZD2mrFsW9kRrFF7xGpCL1ncw3a9lsOAAHMzGYk+8r1WKEsXY3BYg97Qd0Hh+knPu1evUj0b2ZfJS7yIhY3tT2IsLG43O87a4jw/SY7AYpaaKgGUWvYEsLnU2Y7i8tp2hxBvMW+25z6atcQOkE4lZm0x7HXYH/byZK99bzN6WcrXtBjwmGqEGxKFR4sQvDxnC9kUAc1Gt3RYX3BPGx1Gl9QbHxEr+0L51WmpzZnuQBc5VFz3QQSLkbSTD1lpoFzAW4C+nkQLcOHrvNS/rqZ+2NecUPvCAaw5/WZRe01vcsfSSfElJGpPgZNXGm9+Ocf+pHC5mb+JLwNzfZif28ZDU7VI226bc9olpZGofFW4TNe19fNSGgDBtDfnwA4k8ukpHtdr7ecoV8eS+d9bfINwDrdvGdeXPqRWweHz1FpVc1MsDcqAGHdzLvcSbFeyhF8mIBBvoya66G5U9JVxGMzVEqXNwRfTUAf9EyWt2xbQGa2seM+0a+zRv8A8lUkbkIup0A3Y6eNpye1cDkrEU+6pKhe9cjMANTvveX/AIiTxJ8z/MqYuve3O4I5TUtSyYLE4M08yhgVIOqgLmHG9gLW5FteRms7Gx6Jh0poQVVbZjoSbktccDcmZCri8w426c+ciw9QAtfS/Lbjr0mepsXnOa3jdt22UH0kJ9pANGXWYx6673+v7SB8R1+szOWr0qJrcRO9h/vGQlrGE7Xms9pvo5rRK5gWHKOHt4zUYomc2jLUOw2kZN4aS4yuYMPe4JH08ry+a+lsx5ETm/1B/SC9cnjJZrc6kiai5vx358b6TsUq6jcm/j9RacKk1oecyXnTnrHbxGOFjwPjrORSq5SSN/E3kLNHUS88yJ11eq0tLtUOgD5swsMxbMMvK24j08aBoLb9ZxKAFtZKvTXlOfXMtdeerI0uGxxudBbhx8ZK+MJ1Fltz4/zOHhqlh3tRrb+IOJx+tuA4Wt+k5Xja6+WRcbEOahdgjJa1mANvC438xCNW/DU7HS/jKeBxK5hnPcvqbXNuMnxWIGchLsgJAa1rj9pLbs5SePz/AE9Q6HX1/SVxWIsSDpsNvOQ1cQR0JkT1Dx6WnTmVOrF01+YIHPSHnOym4PrKJq8iPC3+9I1PFW1sdxci1zLlh6WjV429NZUR8wNybg7H9tZM2KvzHC3PxM5zsL36+svO/wAZ6kiaq5XUG8Fa5tckERFwb2IsdbWlYm3hvNfLN9XVh3QDnp/Eg95fWw/i3AQcw8+ciew1B1EsidX7OanSMzi400846Veciram4vNYxb6Iv09IJYcoSG+hhe7Eno91UzDnCDifUHwPDfhqH5Sf4xfA8N+GoflU/wDGaxnXy8z9Y2brPqL4Hhvw1D8qn/jF8Dw34ah+VT/xjDXy+D1jlhzn0/8AA8N+GoflU/8AGL4Jhvw9D8pP4lR8w5usIMOc+nPgmG/D0Pyk/iL4Jhvw9D8pP4gfMyuOcIVBPpf4Jhvw1H8pP4lCtSwKlVNLDd5il8lGysBfKx4HpvIuvngMIV59D4ihgEy56eGXM2VbrSFz3unNWHiLRYelgHVWWnhSGUsvdpXKjc2tsNb8rRhr55zSenWAP66z36qnZ4GYrhbEqt8tI6ubLw4/tJThMDYnJhrBsh7tLR/uHT5um8nis6seDHFjc7Hh+0r4muHIO0+gMNg8G6CoKFAKVVjmp0wVDLmGbSy6GIYXAfcwvy5/lpfJtm/8eu0TmRb3a8CpPyt152jvV0Pet009dJ7/AIfA4N7lKWHa1rlUpta4uL2GmmsGtg8IrLTahSzOGKj3KnYEm5C2GgO+9jJ4L5+nz81YcZIMSCbm094o0sE1gKFO5fJlNBQ18ofVStwMpBvtqIBGBChzh0CG9m/phaw3b5Pl/u2l8U83hyYhbbgHbSx87SB8R1AnurVMACR7imSCdBhwSQM12AC6qMj6j7sJTgTfLQptuRlw4bMA2VihC94A6EjaTxX/AErwdcUOdvCRvVB46z6Aw1HBOwRaFIllzKfcKFYWUnKxWxsGX1l74Jhvw1H8pP4lxm9WvmsPrGdhzn0t8Ew34aj+Un8RvgmG/DUfyk/iXDXzNn6xe9E+mfgmG/DUfyqf+MXwPDfhqH5SfxGJr5gzjn9YXvOs+nfgeG/DUPyqf+MXwPDfhqH5VP8AxjDXzAaghrV6+hn058Dw34ah+Un8RfA8N+GoflJ/jGEuOjFFFKhRRRQFFFFAUUUUBjONV7CVs4LGze8soChV94jKSBz7xJPE+d2igNh+wgrBhUbutdRZbAZ6jkHnf3jD0kL+zKWsWJ/4vdXKqWCqrohU8CFcjr0ubqKBcq9l5mdw5XMyGwAtmRlIJHE90C/LwFoKXYARldajAoAi3VSAgDDKRxPfPe3+t1FAOj2GqUWw4dsjWOwJDALqD1K5rG41I20g1OwQ7ZmqE3YVSMoF3yql/DKtrecUUCxQ7IRc9+8tRSjKwGUqXqOQRx/90jyk2MwjO1Ng+UIS1goJJKMu520Y/SKKBzT7NoWFQuS2YsTkQblCSgt3GJpqSw1Nz0tJ8Dt8tTKGcMyhECPYWUMgtx1PMgX0FoooEf8A6bpkMGYlWIJFlBsGcm7AXLMHZS2+XTrDfsHcLVZFswUALZUqOHqJzIYgC+hAFhbeKKBawuAK1C5fN3QqrkChFFhlSx0BIueJ01sBbpxRQFFFFAUUUUBRRRQFFFFA/9k=" />
            <button onClick={exitFull}>Exit fullscreen</button>
          </div>
          <button onClick={triggerFull}>Make fullscreen</button>
        </div>
      );
    };
    2-10. useNotification : please refer to 'MDN Notification'.
    const useNotification = (title, options) => {
      if (!("Notification" in window)) {
        return;
      }
      const fireNotif = () => {
        if (Notification.permission !== "granted") {
          Notification.requestPermission().then((permission) => {
            if (permission === "granted") {
              new Notification(title, options);
            } else {
              return;
            }
          });
        } else {
          new Notification(title, options);
        }
      };
      return fireNotif;
    };
    
    const App = () => {
      const triggerNotif = useNotification("can I steal your kimchi?", {
        body: "I love kimchi dont you"
      });
      return (
        <div className="App" style={{ height: "1000vh" }}>
          <button onClick={triggerNotif}>Hello</button>
        </div>
      );
    };
    2-11. useAxios :
    import defaultAxios from "axios";
    const useAxios = (opts, axiosInstance = defaultAxios) => {
      const [state, setState] = useState({
        loading: true,
        error: null,
        data: null
      });
      const [trigger, setTrigger] = useState(0);
      if (!opts.url) {
        return;
      }
      const refetch = () => {
        setState({
          ...state,
          loading: true
        });
        setTrigger(Date.now());
      };
      useEffect(() => {
        axiosInstance(opts)
          .then((data) => {
            setState({
              ...state,
              loading: false,
              data
            });
          })
          .catch((error) => {
            setState({ ...state, loading: false, error });
          });
      }, [trigger]);
      return { ...state, refetch };
    };
    
    const App = () => {
      const { loading, data, refetch } = useAxios({
        url: "https://yts.mx/api/v2/list_movies.json"
      });
      return (
        <div className="App" style={{ height: "1000vh" }}>
          <h1>{data && data.status}</h1>
          <h2>{loading && "Loading"}</h2>
          <button onClick={refetch}>Refetch</button>
        </div>
      );
    };
    What to learn next to deep into hooks...?
  • useContext
  • useReducer
  • useCallback
  • useMemo