리액트 공식 Document 중 Custom Hook 생성 부분을 번역한 내용이다.
구글 번역기의 도움을 빌렸으며, 어색한 문장은 재량껏 번역하도록 하였다.
ref. https://ko.reactjs.org/docs/hooks-custom.html
hook은 React 16.8의 새로운 추가 기능입니다. 클래스를 작성하지 않고도 상태 및 기타 React 기능을 사용할 수 있습니다.
커스텀 hook을 만들면 컴포넌트 로직을 재사용 가능한 함수로 추출 할 수 있습니다.
Effect Hook 사용에 대해 배우면서 채팅 응용 프로그램에서 친구가 온라인인지 오프라인인지를 나타내는 메시지를 표시하는 아래의 컴포넌트를 보았습니다.
이제 채팅 애플리케이션에도 연락처 목록이 있으며 온라인 사용자의 이름을 녹색으로 렌더링하려고합니다.
위의 비슷한 논리를 FriendListItem 컴포넌트에 복사하여 붙여 넣을 수는 있지만 이상적이지는 않습니다.
따라서 우리는 FriendStatus와 FriendListItem간에 이 로직을 공유하고자 합니다.
전통적으로 React에서는 컴포넌트간에 상태 설정 로직(stateful logic)을 공유하는 두 가지 일반적인 방법으로 render props과 고차원 components를 사용했습니다. 이제 트리에 더 많은 컴포넌트를 추가하지 않고도 Hooks가 여러 동일한 문제를 어떻게 해결하는지 살펴보겠습니다.
두 JavaScript 함수간에 논리를 공유하려면 이를 세 번째 함수로 추출하십시오. Component와 Hook은 모두 Function이므로 문제없이 작동시킬 수 있습니다.
사용자 정의 Hook은 이름이 "use"로 시작하고 다른 후크를 호출 할 수있는 JavaScript 함수입니다. 예를 들어 아래의 useFriendStatus는 첫 번째 사용자 정의 Hook입니다.useFriendStatus에는 새로운 내용이 추가되지 않았습니다. Logic은 위의 Component내에 있던 것과 동일합니다. 컴포넌트에서와 마찬가지로, 무조건 사용자 정의 Hook의 최상위 레벨에서만 다른 Hooks를 호출해야합니다.
React 컴포넌트와 달리 사용자 정의 Hook에는 특별한 표현법(specific signature)이 요구되지 않습니다. 우리는 인수로서 무엇이 필요한지, return이 필요한지를 결정할 수 있습니다. 즉, 그것은 일반적인 함수와 같습니다. 또한, Hook 규칙이 적용됨을 알 수 있도록 이름은 항상 'use' 시작해야합니다.
useFriendStatus Hook의 목적은 친구의 status를 구독하는 것입니다. 이것이 friendID를 인수로 사용하여 이 친구가 온라인인지 여부를 리턴하는 이유입니다.
이제 Custom Hook을 사용하는 방법을 살펴 보겠습니다.
처음에 우리의 목표는 FriendStatus 및 FriendListItem 컴포넌트에서 중복해서 사용되고 있는 로직을 제거하는 것이었습니다. 두 컴포넌트 모두 친구가 온라인 상태인지 알고 싶어합니다.
이제 이 로직을 useFriendStatus Hook으로 만들었으므로 다음과 같이 사용할 수 있습니다.이 코드는 원래 예제와 동일한가요? 예, 정확히 같은 방식으로 작동합니다. 자세히 살펴보면 로직에 아무런 변화가 없었음을 알 수 있습니다. 두 함수 사이의 공통 코드를 별도의 함수로 추출하는 것이 전부였습니다. 사용자 정의 Hook은 React 기능이 아니라 Hook 디자인에서 자연스럽게 따르는 규칙입니다.
사용자 정의 Hook의 이름은 'use'로 시작하도록 해야하나요? 반드시 그렇게 해야합니다. 이 규칙은 매우 중요합니다. 그렇지 않으면 특정 함수에 Hook 호출이 포함되어 있는지 여부를 알 수 없으므로 Hook 규칙 위반을 자동으로 확인할 수 없습니다.
다른 Components가 같은 Hook을 사용하여 상태를 공유할 수 있나요?(Do two components using the same Hook share state?) 사용자 지정 Hook은 상태 설정 로직(stateful logic) (예 : 구독 설정 및 현재 값 기억)을 재사용하는 메커니즘이지만 사용자 지정 Hook을 사용할 때마다 그 안에있는 모든 state와 effects는 완전히 독립적입니다.
Custom Hook은 어떻게 독립적인 state를 사용하나요? Hook에 대한 각 호출은 각기 다른 state를 얻습니다. 우리는 useFriendStatus를 직접 호출하기 때문에 React의 관점에서 컴포넌트는 useState와 useEffect를 호출합니다. 앞에서 배운대로 하나의 구성 요소에서 useState 및 useEffect를 여러 번 호출 할 수 있으며 완전히 독립적입니다.
Hook은 함수이기 때문에 정보를 전달할 수 있습니다.
이를 설명하기 위해 가상 채팅 예제의 다른 Component를 사용합니다. 현재 선택된 친구가 온라인인지 여부를 표시하는 채팅 메시지 수신자 선택기입니다.select 태그로 선택된 friendID를 RecipientID 상태 변수에 유지하고 다른 값이 선택될 때 마다 업데이트합니다.(We keep the currently chosen friend ID in the recipientID state variable, and update it if the user chooses a different friend in the select picker.)
useState Hook 호출은 수신자 ID 상태 변수의 최신 값을 제공하므로 사용자 정의 useFriendStatus Hook에 인수로 전달할 수 있습니다.현재 선택된 친구가 온라인인지 알 수 있습니다. 다른 친구를 선택하고 recipientID 상태 변수를 업데이트하면 useFriendStatus Hook이 이전에 선택한 친구의 구독을 취소하고 새로 선택한 친구의 상태를 구독합니다.
Custom Hook은 React 컴포넌트에서는 불가능했던 로직 공유의 유연성을 제공합니다. form 처리, 애니메이션, 선언적 구독(declarative subscriptions), 타이머 등과 같은 광범위한 use case를 다루는 Custom Hook을 작성할 수 있습니다. 또한 React의 내장 기능만큼 사용하기 쉬운 Hooks를 구축 할 수 있습니다.
너무 일찍 추상화를 추가하는 것은 권장하지 않습니다. 이제 함수 컴포넌트가 더 많은 작업을 수행 할 수 있으므로 평균적으로 컴포넌트 내부의 코드가 더 길어질 수 있습니다. 이것은 일반적인 결과이므로 즉각 Hooks로 분리해야 할 필요는 없습니다. 그러나 사용자 정의 Hook이 복잡한 로직을 간단한 인터페이스 뒤에 숨기거나, 지저분한 컴포넌트를 풀 수있는 경우라면 사용하는 것을 추천합니다.
예를 들어, 임시 방식으로 관리되는 여러 로컬 상태를 포함하는 복잡한 컴포넌트가 있을 수 있습니다. useState는 update logic를 쉽게 중앙 집중화하지 못하기 때문에 Redux Reducer로 작성하는 것이 좋습니다.Reducers는 독립적인 상태에서 테스트하고 복잡한 업데이트 로직 표현을 확장하는 데 매우 편리합니다. 필요한 경우 더 작은 Reducer로 분리 할 수 있습니다. 그러나 React 로컬 상태 사용의 이점을 누리고 싶거나, 다른 라이브러리를 설치하는 것을 원치 않을 수도 있습니다.
그렇다면 Reducer로 컴포넌트의 로컬 상태를 관리 할 수있는 useReducer Hook를 작성할 수 있다면 어떨까요? 단순화된 버전은 다음과 같습니다.
이제 컴포넌트에서 사용할 수 있고 Reducer가 상태 관리를 주도하게 할 수 있습니다.복잡한 컴포넌트에서 Reducer를 사용하여 로컬 상태를 관리해야 하다면 React에 구현된 useReducer Hook을 사용할 수 있습니다. Hooks API 참조에서 다른 내장 Hook와 함께 찾을 수 있습니다.