모달 창 활성화 시 마우스 스크롤로 인해서 모달창 뒤의 UI의 움직임을 방지
import { useLayoutEffect } from 'react'; // 1
const useLockBodyScroll = () => {
useLayoutEffect(() => {
document.body.style.overflow = 'hidden'; // 2
return () => {
document.body.style.overflow = ''; // 3
};
}, []);
};
export default useLockBodyScroll;
바깥 클릭하면 특정 동작을 하도록.
import { useState, useRef } from 'react'; // 1
import useOnClickOutside from './useOnClickOutside.js'
const App = () => {
const [isModalOpen, setModalOpen] = useState(false); // 2
const ref = useRef(); // 3
// 활용 예시
useOnClickOutside(ref, () => setModalOpen(false)); // 5
return (
<div className="backGround">
{isModalOpen ? (
<div ref={ref} className="modal"> // 4
👋 Hey, I'm a modal. Click anywhere outside of me to close.
</div>
) : (
<button onClick={() => setModalOpen(true)}>Open Modal</button>
)}
</div>
);
}
export default App;
useRef는 가상돔을 사용하는 리액트지만 특정 요소의 스크롤위치가 필요하거나 특정 요소에 포커스를 주는 등의 여러가지 상황에서 직접 DOM을 선택해야 하는 경우가 생길 때 사용함.
useState 훅을 활용하여 모달창을 열고 닫을 수 있는 state 생성
ref에 useRef 리턴값 할당.(ref을 설정해준 요소는 직접 DOM을 선택하여서 해당 요소의 여러 데이터 사용 가능)
모달창이 갖고 있는 데이터를 활용하기 위해서 모달창을 의미하는 modal 선택자에게 ref를 할당해줌. 이제 ref는 modal 선택자를 바라봄.
useOnClickOutside 훅은 두 개의 인자를 받음. 첫 번째는 ref, 두 번째는 함수.
// Custom Hook이 Side Effect만 일으키고 return 값이 없으면
// 굳이 리턴 값을 정의해주지 않아도 됩니다!
import { useEffect } from 'react';
const useOnClickOutside = (ref, handler) => {
useEffect(() => {
const listener = (event) => {
if (!ref.current || ref.current.contains(event.target)) { // 2
return;
}
handler(); // 3
};
document.addEventListener("mousedown", listener); // 1
return () => {
document.removeEventListener("mousedown", listener);
};
},
[ref, handler]
);
};
export default useOnClickOutside;
서버에서 데이터를 주고 받기 위한 훅.
// useFetch.js
import { useState, useEffect } from "react";
const useFetch = (url) => { // 1
const [data, setData] = useState({}); ⌉
const [loading, setLoading] = useState(true); ⎮ // 2
const [error, setError] = useState(""); ⌋
const fetchResult = async () => { // 3
try {
const response = await fetch(url); ⌉
const json = await response.json(); ⎮ // 4
setData(json); ⌋
} catch (e) {
setError(e);
} finally {
setLoading(false);
}
};
useEffect(() => {
fetchResult();
}, [url]);
return { loading: loading, data: data, error: error };
};
export default useFetch;
import React from 'react';
import useFetch from './useFetch.js';
const App = () => {
const url = 'https://jsonplaceholder.typicode.com/posts';
const { loading, data, error } = useFetch(url);
return (
<div>
{data.map((list) => {
return (
<div key={list.id}>
<h2>{list.title}</h2>
<span>{list.body}</span>
</div>
);
})}
</div>
);
};
export default App;
참고) data는 받아오는 중일 때는 undefined 리턴 함.