안녕하세요. 김용성입니다.
오늘은 짤막글 포스팅을 해보겠습니다.
주제는 바로 React HOC의 memo에 관련된 부분인데요.
오늘은 React.memo에 대해서만 간단히 알아보도록 하고 HOC에 대해서는 제가 빠른 시일 내에 별도 포스팅을 진행하도록 하겠습니다.
제가 react,react-native를 function형 component로 처음 접했을 때, useState/useEffect 등의 react hook들을 사용하면서 경이로움을 금치 못했습니다.
그러나 특정 상황에서 useState 함수를 실행시킬때마다 해당 state와 상관없는 component도 다시 호출되는 것을 보고, 이럴 때는 렌더링 최적화를 어떻게 해야하나라는 생각을 했습니다.
import {Header} from './components/Header';
const ExampleScreen=()=>{
const [number,setNumber]=useState(0);
const increaseNumber = () => {
setNumber((prevState)=>prevState+1)
}
const decreaseNumber=()=>{
setNumber((prevState)=>prevState-1)
}
return(
<SafeAreaView>
<Header />
<View>
<TouchableOpacity onPress={increaseNumber}>
<Text>+</Text>
</TouchableOpacity>
<Text>{number}</Text>
<TouchableOpacity onPress={increaseNumber}>
<Text>-</Text>
</TouchableOpacity>
</View>
</SafeAreaView>
)
}
간략하게 react-native 코드를 작성해보았습니다.
+버튼과 -버튼을 사용하여 number 값을 조정해주는 화면입니다. 아마 문제 없이 number값이 잘 변경될 것입니다. 그렇지만 분명한 문제점이 존재합니다.
바로 number라는 state값과 전혀 관련이 없는 'Header' 라는 컴포넌트가 setNumber함수가 실행될때마다 렌더링된다는 점입니다.
사실 저는 이게 Strict Mode 관련된 issue인줄 알고, 신경쓰지 않은 채 작업을 진행했습니다.
그렇지만 Header에 어떤 animation을 포함한 요소가 들어있을 때는 렌더링이 계속되다보면 해당 animation이 버벅거림을 볼 수 있었고, 고쳐야겠다고 마음을 먹고 열심히 구글링을 해보았습니다.
그러던 도중 알게 된 것이 바로 React.memo입니다.
Header라는 Component를 살펴보겠습니다.
export const Header = () => {
console.log('Header가 호출되었나요?');
return(
<View style={{flexDirection:'row',alignItems:'center',justifyContents:'space-around'}}>
<Text>left header<Text>
<Text>center header<Text>
<Text>right header<Text>
</View>
)
}
'Header가 호출되었나요?'라는 콘솔 메시지가 계속 터미널창에 뜨는 것을 보며, 아 뭔가 지금 효율적인 렌더링이 되지 않고 있다는 것을 볼 수 있었습니다.
React.memo의 사용법은 상당히 간단합니다. 그냥 컴포넌트를 한번 감싸주면 됩니다.
export const Header = React.memo(() => { //React.memo로 감싸주면 끝!
console.log('Header가 호출되었나요?');
return(
<View style={{flexDirection:'row',alignItems:'center',justifyContents:'space-around'}}>
<Text>left header<Text>
<Text>center header<Text>
<Text>right header<Text>
</View>
)
});
이렇게 하고 다시 화면에서 +,-버튼을 마구마구 눌러보세요. number이라는 state와는 상관없는 Header 컴포넌트는 리렌더링 되지 않습니다. 최적화의 아주아주 기본적인 조건이겠죠?
추가적으로 만약 Header라는 컴포넌트가 부모 컴포넌트의 useState state값을 arguments로 받는다면 해당 setState 함수가 실행될때마다 리렌더링됩니다. 정말 편리하죠??
렌더링해야할 상황, 아닌 상황을 state와 props로 잘 구분해준답니다!
추가적으로 궁금하신 분은 아래의 공식문서를 참고해보시는 것도 좋을 것 같습니다 :)
https://reactjs.org/docs/react-api.html#reactmemo
읽어주셔서 감사합니다!
Header Component 이외에 다른 Component를 추가적으로 사용한다고 할 때 number state 변경에 따른 리렌더링을 막으려면 다른 모든 Component들을 React.memo()로 감싸줘야 하나요??