반응형

useTitle

Title이 변할 때 변화를 감지하는 역할

import { StrictMode, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";

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"), 5000);
  return <div className="App">Hi</div>;
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useTabs

Tab이 변할 때 변화를 감지하는 역할

import { StrictMode, useState } from "react";
import { createRoot } from "react-dom/client";

const content = [
  {
    tab: "Section 1",
    content: "IO'm the content 1",
  },
  {
    tab: "Section 2",
    content: "IO'm the content 2",
  },
];

const useTabs = (initialTab, allTabs) => {
  if (!allTabs || !Array.isArray(allTabs)) {
    return;
  }

  const [currentIdx, setCurrentIdx] = useState(initialTab);

  return {
    currentItem: allTabs[currentIdx],
    changeItem: setCurrentIdx,
  };
};

const App = () => {
  const { currentItem, changeItem } = useTabs(0, content);
  return (
    <div className="App">
      {content.map((section, idx) => (
        <button onClick={() => changeItem(idx)}>{section.tab}</button>
      ))}
      <div>{currentItem.content}</div>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useScroll

Scroll이 변할 때 변화를 감지하는 역할

import { StrictMode, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";

const useScroll = () => {
  const [state, setState] = useState({
    x: 0,
    y: 0,
  });

  const onScroll = () => {
    console.log(`y : ${window.scrollY} x : ${window.scrollX}`);
    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>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

usePreventLeave

사용자가 창을 닫으려는 것을 감지하는 역할

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

const usePreventLeave = () => {
  const listener = (e) => {
    e.preventDefault();
    e.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>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useBeforeLeave

현재 창에서 마우스가 벗어나는 것을 감지하는 역할

import { StrictMode, useEffect } from "react";
import { createRoot } from "react-dom/client";

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("Please don't leave");
  useBeforeLeave(begForLife);
  return (
    <div className="App">
      <h1>Hello</h1>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useClick

클릭을 감지하는 역할

// component가 mount 되었을 때, eventListener을 추가하고 dependency가 없기에 영원하다.

// 이때 dependency를 넣지않고 없애버린다면 매번 update될 때마다 eventListener가 추가될 것이다.
// 따라서 []를 추가해서 componentDidMount때 단 한번만 실행하라는 의미가 될 것 이고 여기서 나오는 return은 componentWillUnMount일 때 동작하게 된다.

// 즉, function을 리턴받았다면 해당 function은 componentWillUnMount로 부터 호출된 것이다.

import { StrictMode, useEffect, useState, useRef } from "react";
import { createRoot } from "react-dom/client";

const useClick = (onClick) => {
  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>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useHover

호버링을 감지하는 역할

// component가 mount 되었을 때, eventListener을 추가하고 dependency가 없기에 영원하다.

// 이때 dependency를 넣지않고 없애버린다면 매번 update될 때마다 eventListener가 추가될 것이다.
// 따라서 []를 추가해서 componentDidMount때 단 한번만 실행하라는 의미가 될 것 이고 여기서 나오는 return은 componentWillUnMount일 때 동작하게 된다.

// 즉, function을 리턴받았다면 해당 function은 componentWillUnMount로 부터 호출된 것이다.

import { StrictMode, useEffect, useState, useRef } from "react";
import { createRoot } from "react-dom/client";

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;
};

const App = () => {
  const sayHello = () => console.log("say hello");
  const title = useHover(sayHello);

  return (
    <div className="App">
      <h1 ref={title}> HI </h1>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useConfirm

확인 혹은 취소를 감지하는 역할

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

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>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useFadeIn

특정 시간 이후 fade-in 효과를 나타냄

import { StrictMode, useEffect, useRef } from "react";
import { createRoot } from "react-dom/client";

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 fadeInP1 = useFadeIn(3, 4);

  return (
    <div className="App">
      <h1 {...fadeInH1}>Hello</h1>
      <p {...fadeInP1}>hihihi</p>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useFullScreen

풀스크린을 감지하는 역할

import { StrictMode, useEffect, useState, useRef } from "react";
import { createRoot } from "react-dom/client";

const useFullScreen = (onFullS) => {
  const element = useRef();
  const triggerFull = () => {
    if (element.current) {
      element.current.requestFullscreen();
    }

    if (onFullS && typeof onFullS === "function") {
      onFullS(true);
    }
  };

  const exitFull = () => {
    document.exitFullscreen();
    if (onFullS && typeof onFullS === "function") {
      onFullS(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">
      <div ref={element}>
        <img src="https://i.ibb.co/R6RwNxx/grape.jpg" />
        <button onClick={exitFull}> Exit Full </button>
      </div>
      <button onClick={triggerFull}> Make Full </button>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);

 

useNetwork

네트워크 감지 역할

import { StrictMode, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";

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);

    return () => {
      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 status = useNetwork(handleNetworkChange);

  return (
    <div className="App">
      <h1>{status ? "Online" : "Offline"}</h1>
    </div>
  );
};

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
반응형