React Hooks

useEffect

정중식 2019. 12. 12. 08:38

useEffect

useEffect는 componentDidmount, componentWillUnMount, componentDidUpdate 이다.

 

2개의 인자를 받는데, 첫번째는 function으로써의 effect고,

두번째에 넣은 인자 상태가 바뀌면 첫번째 인자가 다시 실행된다.

 

useEffect(sayHello, []); // 2번째인자값을 이런식으로 비우면 한번만 실행됨

 

useTitle

// 5초후 브라우저의 제목이 Home로 바뀜

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const useTitle = initialTitle => {
  const [title, setTitle] = useState(initialTitle);
  const updateTitle = () => {
    const htmlTitle = document.querySelector("title"); // 헤더에있는<title>
    htmlTitle.innerText = title;
  };
  useEffect(updateTitle, [title]);
  return setTitle;
};

const App = () => {
  const titleUpdater = useTitle("Loading...");
  setTimeout(() => titleUpdater("Home"), 5000);
  return (
    <div className="App">
      <div>Hi</div>
    </div>
  );
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

 

useRef()

  • useRef() => reference는 기본적으로 component의 어떤 부분을 선택 수 있는 방법이다.

    • 예) document.getElementById()처럼 요소를 가져와 사용

  • react에 있는 모든 컴포넌트는 reference element를 갖고있음

5초 뒤에 input창이 포커스됨

 

useClick

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

const useClick = onClick => {
  if (typeof onClick !== "function") {
    return;
  }
  const element = useRef();
  useEffect(() => {
    if (element.current) {
      element.current.addEventListener("click", onClick);
    } // useEffect가 마운트되거나 업데이트 되었을때 실행되고
    return () => {
      if (element.current) {
        element.current.removeEventListener("click", onClick);
      }
    }; // 컴포넌트가 제거 (WillUnmount)될때 실행됨
  }, []);
  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");
ReactDOM.render(<App />, rootElement);

useConfirm & usePreventLeave

  • useConfirm
import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

const useConfirm = (message = "", onConfirm, onCancel) => {
  if (!onConfirm || typeof callback !== "function") {
    return;
  } // 함수가아니면 빈 값을 리턴.
  if (onCancel && typeof callback !== "function") {
    return;
  }
  // confirm은 alert와 비슷한 브라우저 기능임
  const confirmAction = () => {
    if (confirm(message)) {
      onConfirm(); // 창의 확인버튼 누를시
    } else {
      onCancel(); // 창의 취소 버튼 누를시
    }
  };
  return confirmAction;
};

const App = () => {
  const deleteWorld = () => console.log("Delete 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");
ReactDOM.render(<App />, rootElement);
  • usePreventLeave

일반적인 웹 사이트에서 창을 닫을때 "아직 저장하지 않았어!" 라고 말해주는것

 

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

export const usePreventLeave = () => {
  const listener = event => {
    event.preventDefault();
    event.returnValue = ""; // 이걸 넣어주지않으면 크롬에서 이벤트 작동안함
  };
  //beforeunload는 윈도우 함수, 확인기능
  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");
ReactDOM.render(<App />, rootElement);

useBefore(Leave

탭을 닫을때 실행되는 함수

페이지를 벗어날때 실행됨

 

//  실행이 잘 안되었음

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

export 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);
  }, []); // return => componentWillUnMount , []은 계속해서 이벤트가 추가되는걸 막아줌, 단 한번만 실행됨
};

const App = () => {
  return (
    <div className="App">
      <h1>Hello</h1>
    </div>
  );
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

 useFadeIn

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

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}>sdfisdfsdffsd</p>
    </div>
  );
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

useNetwork

navigator가 online 또는 offline이 되는걸 막아줌

 

import React, { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom";

export 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>
  );
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);