state
와 그 외에도 다른 react의 기능들을 사용할 수 있게 해줍니다.state
와 기타 다른 사이드 이펙트 사용 가능 functional component
class
가 아닌 함수로 component 를 만드는 것 입니다.- 원래도 존재하던 component 지만 이전에는
state
를 가지지 않고 보이기만 하던 component 로 주로 dumb componet 로만 사용되었습니다.hook
이 나오면서 class component 보다 주목받고 있습니다!
hook이 나오게된 과정
- 컴포넌트간 상태 관련 로직을 재사용하기 어렵습니다.
-> 매번 같은 상태 관리 로직을 복붙해야했고, 공통화되지 않다보니 컴포넌트마다 변경사항을 수정해야하는 어려움이 있었습니다.- 컴포넌트가 커질수록 로직이 복잡해집니다.
-> componentDidmount 에서 너무 많은 일을 하게됩니다.
컴포넌트마운트 시api
호출 및event listener
를 가져오는 작업을 한개의 메소드에서 진행하다보니 subscribe 단일 책임 원칙(SRP)에서 벗어나게됩니다.class
에서 발생되는 혼란
->this
키워드를 사용하면서prop
으로 받아오는 값이 변할 수 있으므로 보장되지 않아 버그를 야기합니다.
class
는 new
키워드를 통해서 instance 를 생성하고 instance 안에 있는 render 메소드를 호출하게 되면서 화면을 그리게됩니다.
functional의 경우에는 매번 함수를 호출하여 render 를 동작시킵니다. ( render = 함수호출 )
🌠 이해를 돕기위한 예시코드를 살펴보겠습니다. 🌠
export const ComponentA = () => {
const [firstName, setFirstName] = useState(''); // 첫 줄에 usestate를 통해 정의
useEffect(() => {}, []); // 이후에 useEffect
const [lastName, setLastName] = useState('');
useEffect(() => {}, []);
// ...etc logic
}
react 에서 hook
들은 선언해둔 순서에 따라 state
에 접근할 수 있는 index
값이 부여됩니다.
조건부에 따른 hook
호출을 하게된다면 index
의 결과값이 달라질 수 있기 때문에 조건부를 타지 않도록 항상 최상단에 모든 hook
들을 선언해야합니다.
state
를 지칭하고 있는 cursor
값이 있습니다.
hook
들이 호출되면 cursor
의 index
가 늘어납니다.
export const ComponentA = () => {
const [firstName, setFirstName] = useState(''); // [0] cursor index = 0
useEffect(() => {}, []); // [1] cursor index = 1
const [lastName, setLastName] = useState(''); // [2] cursor index = 2
useEffect(() => {}, []); // [3] cursor index = 3
// ...etc logic
}
index = 1
인 useEffect 를 조건부에 따라 호출하게 된다면,
처음 호출 당시에는 [0], [1], [2], [3] 코드를 실생하여 index
가 0
,1
,2
,3
이지만, 조건부 호출시에는 [0], [2], [3] 의 코드가 index
0
, 1
, 2
순서로 호출됩니다.
이럴경우에 hook
이 갑자기 사라지거나 하기 떄문에 index
를 같은 hook
이라 볼 수 없습니다. 이런 경우 의도치 않게 버그가 발생됩니다.
react 함수 외에 순수함수 등에서 hook
을 호출하게되면 error 가 발생합니다.
어떻게보면 당연한거네요.. ㅎㅎ
[react-native] useWindowDimensions
export const ComponetA = (props) => { const {window, height} = useWindowDimensions(); {...etc code} }
화면의 width, height 를 계산하게 될 때
dimensions.getWindow
함수를 매번 함수 컴포넌트 바깥에서 선언하였습니다.이것을 함수형 컴포넌트 내부에서
hook
으로 호출하면 불필요한 코드를 많이많이 줄일 수 있습니다.
useWindowDimensions()
라는hook
을 바로 사용하지 않고,useScreenSize()
라는커스텀 hook
을 별도로 만들어서 사용하게되면 reactNative 뿐 아니라 react 에서도 적용이 가능합니다.
[react-native] useBackHandler
export const ComponentA = (props) => { useBackHandler(() => { return true }); {...etc code} }
Android를 위해서 사용하는
hook
입니다.
하드웨어 Back 키를 누르게 될 때 동작을 처리하는hook
입니다.
반드시 boolean 값을 return 해주어야합니다.
true
: event를 handling하고 다음 Component 로 넘기지 않습니다.false
: Component 에서 handling하지 않고 다른 Component 제어권을 넘깁니다.
-> 주로 Modal 을 닫거나 Bottom Sheet 를 닫는 행동을 할 때 사용합니다.npm install @react-native-community/hooks
react-native package 에 있지 않고
react-native-community 의hook
package_에 들어가있어 추가로 설치해주어야합니다.
[react-native] useAppState
export const ComponentA = (props) => { const currentAppState = useAppState(); // active, background, inactive(only ios) {...etc code} }
현재 APP의 상태가 어떤지 return 해줍니다.
APP의 경우 기본적으로 Foreground 에 있는지, Background 에 있는지 등의 상태가 됩니다.
Foreground 에 있으면
active
,
Background 에 있으면Background
를 값을 return 해줍니다.요구사항에 따라서 유용하게 사용되는
hook
입니다.npm install @react-native-community/hooks
useBackHandler 와 마찬가지로 react-native package 에 있지 않고
react-native-community 의hook
package_에 들어가있어 추가로 설치해주어야합니다.
[react-navigation] useNavigation, useRoute
export const ComponentA = (props) => { const navigation = useNavigation(); const routes = useRoute(); {...etc code} }
react-navigation 에서 자주 사용하는
useNavigation
,useRoute
입니다.
props
에 들어있는 navigation prop 과 route prop 에 접근할 수 있습니다.매번
props
에 navigation prop 과 route prop 를 정의하여 사용할 수 있지만 실무에서는hook
을 자주 사용하기 때문에hook
을 호출하게 되어있습니다.
[react-navigation] uselsFocused, useFocusEffect
export const ComponentA = (props) => { const isFocused = uselseFocused(); useFocusEffect(useCallback(() => { //focus가 되었을 때의 처리 }, [userId])); {...etc code} }
Bottom Tab Navigator 에서 많이 사용됩니다.
Tab
혹은Screen
에 포커싱의 여부를 알고자할 때 사용합니다.
uselsFocused
는 boolean 값을 return 해줍니다.useFocusEffect
는useEffect
처럼 변경이 되었을 때 callback 을 처리해줍니다.
[react-navigation] useScrollToTop
export const ComponentA = (props) => { const scrollViewRef = useRef(); useScrollToTop(scrollViewRef); {...etc code} }
ScrollView를 최상단으로 올릴 때 사용합니다.
Bottom Tab Navigator 에서 자주 사용됩니다.
Bottom Tab 하단에 있는 아이콘 클릭 시 화면의 최상단으로 이동하는effect
가 필요할 때 작성하게됩니다.
[react-use] useMount
export const ComponentA = (props) => { useMount(() => { // on mount 처리 }); {...etc code} }
useMount
는 Component가 mount 된 시점에 callback 을 호출합니다.life cicle 에서 에러와 혼동없이 원하는 부분을 짚어내기 위해 사용한다고 합니다.
Component 가 mount 되는 시점은
useEffect
를 통해서도 알 수 있지만, 유지보수를 하다보면 어떤 의미의useEffect
인지 모르는 상황이 발생하거나, 잘 동작하던 코드를 지우게 되면서 버그를 겪게되는 경우가 많다고합니다.이것을 대비하기 위해 useMount 를 통해 필요한 작업을 한다고 합니다.
[react-use] usePrevious
export const ComponentA = (props) => { const [count, setCount] = useState(0); const prevCount = usePrevious(count); {...etc code} }
usePrevious
는 이전에 사용했던state
값을 알아내고자할 때 사용합니다.마지막으로 갖고 있던
state
를 비교할 일이 생긴다면 유용하겠네요!
지난 게시글 https://velog.io/@bi-sz/ReactNative-Component 에서 Class Componet 들을 만들어두었는데,
다음 게시물에서는 이 컴포넌트들을 functional Component 로 변경해보고 사용할 hook
들은 추가해보도록 하겠습니다!