React에서 사용하는 Hook 중에서 UseEffect와 UseRef에 대해서 좀 더 알아보고 정리해보는 시간을 갖고싶어서 이 글을 작성한다.
https://ko.reactjs.org/docs/hooks-effect.html
1. UseEffect란?
의존값으로 Props나 State등을 배열로 받아 해당 값이 변할 경우 UseEffect()의 첫번째 인자로 받은 함수를 실행시킬 수 있다. 밑에 세 가지 방법으로 사용되는데
1-1. 최초 렌더링 시에만 실행시키고 싶은 경우
useEffect의 두번째 인자로 [] 빈 배열을 설정해주면 최초 렌더링 시에만 한번 수행한다. 아래 예제는 최초 진입 시 그룹과 방 정보를 api를 통해 가져온 후 소켓 연결까지 하는 코드다.
const updateInitState = () => {
fetchGroups().then((groupData) => {
console.log('group data in', groupData);
setGroup(groupData);
fetchRooms().then((roomData) => {
console.log('room data in', roomData);
setRoom(roomData);
setLoaded(roomData !== undefined)
if (roomData !== undefined) {
initSocketConnection();
}
})
});
}
useEffect(()=>{
updateInitState();
}, []);
1-2. 의존 값 변경 시 실행시키고 싶은 경우
useEffect의 두번째 인자로 [의존값, 의존값, ......] 배열을 설정해 주면 배열 안에 있는 의존 값(State or Props...etc) 변경 시 함수가 실행된다. 이건 마치 ECS 시스템에서 Component가 변경되면 지켜보던 System이 돌아가는 것과 비슷하다.
아래 예제는 대화방 내에서 방 ID나 유저 변경 시 소켓을 통해 유저가 입장한 것을 알리고 대화 목록을 업데이트 해주는 기능이다.
useEffect(()=>{
initSocketConnection();
if (roomId !== null && roomId !== undefined) {
socket.emit('joinRoom', roomId, currnetUser);
var date = new Date();
var time = date.getTime();
fetchChats(roomId).then((res) => {
var result = res.filter((chat) => {
var d = new Date(chat.createAt);
return d.getTime() < time;
}).map(chat => {
return({name : chat.userName, message : chat.message, datetime :chat.createAt})
});
setChat(result);
}
);
}
},[roomId, currnetUser]);
1-3. 렌더링 할때마다 실행시키고 싶은 경우
두 번째 인자에 아무것도 넣지않고 실행시 렌더링될때마다 실행되는 것을 볼 수 있다. 다만 주의할 점은 실행하고 싶은 함수 내에 State변경함수 같은 걸 넣으면 State변경시 재렌더링이 일어나 무한루프에 빠질 수 있으므로 주의해야한다!!
useEffect(()=>{
//실행하고싶은 함수 작성
});
2. UseRef란?
특정 Element를 참조할 수 있는 Reference 변수를 선언할 수 있다. 예를들어 부모 컴포넌트가 자식 컴포넌트를 참조하여 자식컴포넌트의 값을 변경할 수 있다.
아래 예제는 특정 div에 스크롤이 가능하도록 설정한 후 채팅 메시지가 업데이트 될때마다 useEffect내에서 스크롤 위치를 맨 아래로 옮길 수 있도록 작성된 코드다.
UseRef로 ref변수 선언 후 , div의 ref={변수} 로 넣어주면 해당 div를 참조할 수 있다.
참조 값의 값을 변경하려면 talkListRef.current 로 받아와 속성 값을 변경 시킬 수 있다.
//UseRef선언
const talkListRef = useRef();
//스크롤 위치 업데이트용 UseEffect함수
useEffect(() => {
if (talkListRef.current) {
talkListRef.current.scrollTop = talkListRef.current.scrollHeight;
}
}, [chat])
//TalkList 컴포넌트
const talkList = () => {
return(
<div className="div-talk-list" ref={talkListRef}>
{renderChat()}
</div>
);
}
한 번 정리해 놓으니 다음엔 헷갈리지않고 더 잘 쓸 수 있을 것 같다.
'개발 Study > React' 카테고리의 다른 글
[React/Redux] Redux 사용법 (1) -State/Action/Reducer/Store (0) | 2022.08.04 |
---|---|
[Error] Redux createStore 에러 처리 (deprecated) (0) | 2022.08.01 |
[React] Material UI를 이용한 FormDialog 구현하기 (1) | 2022.07.29 |
[React] 실시간 채팅 구현하기 - Login 페이지 생성 (3) | 2022.07.25 |
[React/Error] React 버전 변경/다운그레이드 및 에러 해결 (2) | 2022.07.06 |
댓글