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를 갖고있음
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);