함수형 컴포넌트에 업데이트 조건을 걸자.
로직을 재사용하기위한 React의 고급 기술이다.
구체적으로, 고차첨포넌트는 컴포넌트를 가져와서 새 컴포넌트에 반환하는 함수입니다. (매개변수로 컴포넌트를 전달한다.)
매개변수에 똑같은 prop을 받으면 리렌더링을 하지않는다.
OptimizedTest.js
import React, {useState, useEffect} from 'react';
const OptimizedTest = () => {
const [count, setCount] = useState(1);
const [text, setText] = useState('');
const TextView = ({text}) => {
useEffect(()=>{
console.log(`Update :: Text : ${text}`);
})
return <div>{text}</div>
}
const CountView = ({count}) => {
useEffect(()=>{
console.log(`Update :: Count : ${count}`);
})
return <div>{count}</div>
}
return(
<div style={{ padding:50 }}>
<div>
<h2>count</h2>
<CountView count={count}/>
<button onClick={()=>setCount(count+1)}>+</button>
</div>
<div>
<h2>text</h2>
<TextView text={text}/>
<input type="text" value={text} onChange={(e)=>setText(e.target.value)}/>
</div>
</div>
)
}
export default OptimizedTest;
CountView 값이 변하지않았는데도, TextView 값이 변화하여, 같이 리렌더링이 되고 있다.
const CountView = React.memo(({ count }) => {
useEffect(() => {
console.log(`CountA Update - count : ${count}`);
});
return <div>{count}</div>;
});
const TextView = React.memo(({ text }) => {
useEffect(() => {
console.log(`CountA Update - text : ${text}`);
});
return <div>{text}</div>;
});
OptimizedTest2.js
import React, { useEffect, useState } from "react";
const CounterA = React.memo(({count}) => {
useEffect(()=>{
console.log(`CounterA update - count:${count}`);
})
return <div>{count}</div>
})
const CounterB = React.memo(({obj}) => {
useEffect(()=>{
console.log(`CounterB update - count:${obj.count}`);
})
return <div>{obj.count}</div>
});
const OptimizedTest = () => {
const [count, setCount] = useState(1);
const [obj, setObj] = useState({
count:1,
})
return(
<div style={{ padding:50 }}>
<div>
<h2>Counter A</h2>
<CounterA count={count}/>
<button onClick={()=>setCount(count)}>A Button</button>
</div>
<div>
<h2>Counter B</h2>
<CounterB obj={obj}/>
<button onClick={()=>setObj({
count:obj.count
})}>B Button</button>
</div>
</div>
)
}
export default OptimizedTest;
CounterB 도 count의 값이 변화되지않았음으로 console이 찍히지 않아야하는데.. 작동이 되고있다. 이유는 obj가 객체 이기때문이다.
얕은 비교는 객체의 값을 비교하는 것이 아니라 객체의 주소가 같은지 비교하는 것이다. 그래서 같은 값이여도, 주소가 다르기 때문에 다른 것이다.
const areEqual = (prevProps, nextPrpos) => {
return true; //이전 프롭스 현재 프롭스가 같다 -> 리렌더링을 일으키지 않는다.
return false; //이전과 현재가 다르다 -> 리렌더링을 일으킨다.
}
const CounterB = ({obj}) => {
useEffect(()=>{
console.log(`CounterB update - count:${obj.count}`);
})
return <div>{obj.count}</div>
};
const areEqual = (prevProps, nextPrpos) => {
if(prevProps.obj.count === nextPrpos.obj.count){
return true;
}
return false;
}
const MemoizedCounterB = React.memo(CounterB, areEqual);
<MemoizedCounterB obj={obj}/>
이렇게 넣어주면 리렌더링이 되지 않는다.
const areEqual = (prevProps, nextPrpos) => {
return prevProps.obj.count === nextPrpos.obj.count;
}
if문을 저런식으로 짧게 넣어줄 수 도 있다.