
Prop Drilling으로 인해 불필요한 재렌더링이 발생할 수 있습니다.
React component는 prop이 변경될 때 항상 렌더링되므로 단순히 prop을 자식 컴포넌트로 전달하는 중간 컴포넌트는 prop을 전달할 때 강제로 렌더링됩니다.
따라서 이 과정에서 메모리와 성능 문제가 발생할 수 있습니다.
원인
해결
as-is
<Page user={user} avatarSize={avatarSize} />
...
<PageLayout user={user} avatarSize={avatarSize} />
...
<NavigationBar user={user} avatarSize={avatarSize} />
...
<Link href={user.permalink}>
<Avatar user={user} size={avatarSize} />
</Link>
to-be
function Page(props) {
const user = props.user;
const userLink = (
<Link href={user.permalink}>
<Avatar user={user} size={props.avatarSize} />
</Link>
);
return <PageLayout userLink={userLink} />;
}
// 이제 이렇게 쓸 수 있습니다.
<Page user={user} avatarSize={avatarSize} />
...
<PageLayout userLink={...} />
...
<NavigationBar userLink={...} />
...
{props.userLink}
클래스형 컴포넌트에서 componentDidMount는 이벤트 리스너를 할당하는 데 사용하는 일반적인 함수였으며 함수형 컴포넌트에서는 해당 역할에 useEffect를 사용합니다.
원인
해결
unmount 될 때 - useEffect(func, [])
특정값 update 직전 - useEffect(func, [특정값])
=> re-render -> 이전 effect clean-up -> effect
function App() {
const [varA, setVarA] = useState(0);
const [varB, setVarB] = useState(0);
// 이렇게 하면 안된다!
useEffect(() => {
const timeoutA = setTimeout(() => setVarA(varA + 1), 1000);
const timeoutB = setTimeout(() => setVarB(varB + 2), 2000);
return () => {
clearTimeout(timeoutA);
clearTimeout(timeoutB);
};
}, [varA, varB]);
return (
<span>
Var A: {varA}, Var B: {varB}
</span>
);
}
function App() {
const [varA, setVarA] = useState(0);
useEffect(() => {
if (varA > 0) return;
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]); // 이렇게 해야한다. 모든 디펜더시가 배열에 들어가 있다.
return <span>Var A: {varA}</span>;
}
큰 구성 요소를 래핑할 수 있고 코드를 읽을 때 해독하기 어려울 수 있다는 단점이 있습니다.
이 경우 함수를 사용하여 렌더링 논리를 추상화합니다.

map() 사용 시 해당 요소 또는 구성 요소의 적절한 추적을 처리할 수 있도록 Key는 고유해야 합니다. 인덱스를 Key로 사용하는 경우 해당 키는 경우에 따라 중복될 수 있으므로 피해야 합니다.
원인
배열의 인덱스를 Key로 사용하면, 추가, 삭제 등과 같은 작업을 수행하면 엘리먼트의 순서가 변경될 수 있습니다. 이 경우 Key는 이전과 같게 되고 React는 이전과 동일한 요소/구성 요소라고 가정하며 따라서 상태의 정확한 변화를 감지할 수 없습니다.

Virtual DOM을 생성해서 업데이트된 부분과 기존의 돔을 비교하는 과정을 통해 변경된 ui부분을 업데이트하는데,
어떠한 부분이 기존의 돔과 비교하여 변경이 되었는지 확인하기 위해 각 엘리먼트에 중복성이 없는 유일한 값을 key값으로 할당해야 합니다.
또한 재사용 가능한 컴포넌트가 계속 사용되다 보면 하나의 UI컴포넌트안에 중복이 일어날 수 있습니다.
해결
복잡한 코드에선 대부분 fetch나 api를 통한 연산 이후 데이터를 렌더링하게 되는데, 대부분 비동기로 이루어지기 때문에 이로 인해 인덱스의 고유값이 깨지게 되고 이는 예기치못한 결과로 이어질 수도 있다고 한다.
고유성이 보장되는 Database의 id나, global 변수를 이용해 id를 생성하고 이를 key로 사용해주는것이 좋다.
const App = ({numbers}) => {
return (
<ul className="App">
{numbers.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
};
원인
해결
as-is
const App = () => {
const handleClick = () => {
console.log("You Clicked???????");
};
return <button onClick={() => handleClick()}>Click me</button>;
};
to-be
const App = () => {
const handleClick = () => {
console.log("You Clicked???????");
};
return <button onClick={handleClick}>Click me</button>;
};
as-is

to-be

const Main = () => {
const [name, setName] = useState("Ateev");
const Sub = () => {
return <h1 className="p-5">Hello {name}, I am the child of Mr & Mrs Khana</h1>;
};
return (
<>
<Sub />
</>
);
};