이제 useEffect를 사용한 첫 번째 hooks을 작성해보자.
문서의 제목을 업데이트 시켜주는걸 담당하는 hooks을 작성할거다.
제목을 업데이트할 수 있게 setTitle을 return 해줄거다.
useEffect는 component가 mount 될 때 updateTitle을 부를거고,
title이 업데이트되면 updateTitle을 다시 부를거다.
아직 updateTitle을 부르지 않았기 때문에 지금 바로 무슨 일이 생기진 않는다.
titleUpdater를 어딘가에서 부르면 title이 바뀌게 된다.
[title]이 바뀌면 updateTitle이 다시 불러지게 된다.
시간지연을 줘서 변화를 확인해보자.
dependency는 매우 좋다.
하나의 value가 바뀌면 아래처럼 setTitle을 이용할거고 이것이 시발점이 되어서
모든 것들이 작동하게 되는거다.
<소스코드>
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"); //헤드에 하나 있는 타이틀을 의미
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>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<useClick>
useClick을 통해서 references가 뭔가 배워볼거다.
reference는 기본적으로 우리의 component의 어떤 부분을 선택할 수 있는 방법인데,
document.getElementByID()를 사용한것과 동등하다.
input에 포커스를 하면 3초 뒤에 활성화되도록 해보자.
리액트에 있는 모든 컴퍼넌트는 reference element를 가지고 있다.
3초뒤에 input을 콘솔로그에 보여주겠다.
const potato = useRef();
setTimeout(() => potato.current.focus(), 3000);
3초 뒤에 input창에 포커스가 활성화된다.
이제 우리는 title에 접근해서 우리가 하고싶은 모든 걸 할 수가 있다.
여기에 useEffect를 적어줄거다.
우리는 useClick을 사용해서 useRef()를 만들었고,
우린 같은 reference를 return 해줬다.
그리고 주어진 reference를 title에 줬다.
이제는 상호작용을 할 수 있는 상태가 된거다.
useEffect에서 할 일은 reference 안에 element.current가 있는지 확인하는 거다.
그리고 조건이 만족되면 Click 이벤트를 부여하는거다.
이 모든 것들은 reference가 있어서 작동하는거다.
reference를 return 해서 저기에 넣어줬지만,
element에 eventListener를 추가해줬다.
하지만 이 이론에서 꼭 해야하는건 정리를 해줘야 된다.
componentWilUnMount가 될 때 저 eventListener를 지워야한다.
이게 useEffect의 두 번째 부분이다.
useEffect는 componentDidMount 상태에 동작을 한다.
그래서 저 케이스에서는 component가 mount 되었을 때 event를 추가해준다.
componentWillUnMount 일때는 이벤트가 발생한뒤 정리할 필요가 있다.
지금까지 어떤 function도 return 하지 않았지만 이제는 할 필요가 있다.
dependency가 없으므로 뭔가 update 되었을때를 고려하지 않아도 된다.
dependencyt가 존재하지 않는 한
useEffect에 함수를 넣으면 componentDidMount, componentDidUpdate 때 호출 될거다.
dependencyt가 존재한다면 저 함수는 componentDidMount일 때만 호출 될거다.
useEffect를 return 받은 그 함수는 componentWillUnMount때 호출될거다.
다시 말하자면 function을 리턴받았다면 그 함수는 componentWillUnMount로 부터 호출된거다.
컴포넌트가 mount 되었을 때 eventListener를 추가해줄거고,
dependency가 없기 때문에 이건 영원할거다.
dependency를 넣지않고 없애버린다면?
매번 update 될때마다 eventListener가 추가되므로 우리가 원하는게 아니다.
추가를 해줘야 componentDidMount때 단 한 번만 실행되라는 의미가 된다.
그리고 나서 저기 있는 함수를 return 할건데 componentWillUnMount 때 호출될거다.
component가 mount 되지 않았을 때 eventListener가 배치되게 하고 싶지 않다.
함수가 아니면 아무 일도 발생하지 않는다.
<코드 기록>
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);
}
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");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
※ 본 포스팅은 개인 공부 기록을 목적으로 남긴 글이며 본 사실과 다른 부분이 있다면 과감하게 지적 부탁드립니다.
'React > React Hooks' 카테고리의 다른 글
[Hooks] 5. Introduction to useEffect (0) | 2020.08.22 |
---|---|
[Hooks] 4. useTabs (0) | 2020.08.21 |
[Hooks] 3. useInput (0) | 2020.08.18 |
[Hooks] 2. Introduction to useState (0) | 2020.08.18 |
[Hooks] 1. 사용법 배우기 (0) | 2020.08.14 |
댓글