상위 컴포넌트의 데이터를 하위 컴포넌트에 props로 전달하는 방식은 아주 좋은 방법입니다.
그러나 하위 컴포넌트에서 직접 그 데이터를 사용하지 않고 하위 컴포넌트의 하위 컴포넌트에서 사용하게 된다면, 그것이 하위의, 하위의, 하위의 컴포넌트가 사용하는 깊이까지 내려간다면 원래 컴포넌트에서 해당 props가 어떤 의미인지, 어떤 맥락에서 쓰이는지 찾기 어려울 것입니다. 또, 중간에 props를 전달만 해주는 컴포넌트들은, 이렇게 전달만 하는 props가 한두개라면 괜찮지만 많아진다면 관심사의 분리가 이뤄지지 않고 지저분한 코드가 될 수 있습니다.
이렇게, 연속된 props 전달을 통해 원 컴포넌트와 props를 사용하는 하위 컴포넌트 사이가 멀어지면서 생기는 현상을 ‘props drilling’이라고 합니다. 마치 props가 원 컴포넌트에서 드릴을 파고 하위의 하위 컴포넌트까지 깊게 들어가는데서 유래했습니다.
1. 전역상태관리 사용
React에서 직접 만들고 권장하는 Context API, 그 외 Redux, Recoil 등의 상태관리 라이브러리가 있습니다. 처음에 전역적으로 관리가 필요한 상태를 상위 컴포넌트에서 등록해주면, 해당 상태가 필요한 컴포넌트에서 상태를 불러오는 코드를 통해 props drilling 없이 접근할 수 있습니다.
2. { Children } 활용
Children을 활용하여 props 전달을 깔끔하게 해낼 수 있습니다.
import './App.css';
import { Boy } from './Boy';
import { Parent } from './Parent';
function App() {
const userName = 'Crocs';
const Parent = ({ children }) => {
return (
<div>
{children}
</div>
);
};
export const Boy = ({ userName }) => {
return (
<div>
<p>
`I'm a boy, My name is {userName}`
</p>
</div>
);
};
return (
<div className="App">
<Parent>
<Boy userName={userName} />
</Parent>
</div>
);
// 결과 : `I'm a boy, My name is Crocs`
}
export default App;
React Context는 React에 내장된 전역 상태관리 도구로써, 별도의 라이브러리 설치 없이 사용가능하며, props 전달없이 특정 상태 값을 공유할 수 있습니다.
import { createContext } from 'react';
const Context = createContext(defaultValue);
import { useContext } from 'react';
import { context } from './context.js';
export default function Section({ children }) {
const state = useContext(Context); // useContext로 상태 불러오기
return (
<section className="section">
<Context.Provider value={level + 1}> // Provider로 감싸주기
{children}
</Context.Provider>
</section>
);
}
useContext를 통해 context 값을 불러와, Context.Provider로 사용하려는 컴포넌트에 감싸줍니다. Provider 는 반드시 value 속성값이 필요한데, 컴포넌트 간에 공유하고자 하는 값을 넣어주면 됩니다.