React에서 데이터 다루기
React 앱은 컴포넌트라는 독립적인 UI요소를 조합하여 만든다. 컴포넌트 간의 데이터 관리는 React에서 중요한 역할을 한다. Props, State, Context는 컴포넌트에서 데이터를 다루는 기술들이다.
Props
Props는 "properties"의 줄임말이다. React에서 컴포넌트 간 데이터를 전달하는 메커니즘으로 부모 컴포넌트에서 자식 컴포넌트로 데이터를 전달하기 위해 Props를 사용한다. Props의 데이터는 읽기전용으로 전달되고, 자식 컴포넌트에서는 Props를 변경할 수 없다.
// 부모 컴포넌트
function ParentComponent() {
const name = "정인";
return (
<div>
<ChildComponent name={name} />
</div>
);
}
// 자식 컴포넌트
function ChildComponent(props) {
return (
<div>
<p>Name: {props.name}</p> // Name : 정인
</div>
);
}
ParentComponent에서 name을 Props로 전달하고, ChildComponent에서 Props를 출력한다. Props는 자식 컴포넌트에서 Props 객체를 통해 접근할 수 있다.
Props를 받을때, 구조분해할당을 사용하여 다음과 같이 연산자 사용을 줄일 수 있다.
function ChildComponent({name}) {
return (
<div>
<p>Name: {name}</p> // Name : 정인
</div>
);
}
Props의 초기값을 미리 정의할 수 있다. defaultProps 프로퍼티를 할당하면 된다.
function ChildComponent({name}) {
return (
<div>
<p>Name: {name}</p> // Name : 정인
</div>
);
}
ChildComponent.defaultProps = {
name: "리액트"
}
State
Props는 컴포넌트 간 데이터 전달에 사용된다면, State는 컴포넌트 내에서 관리되는 데이터이다. 컴포넌트 내에 상태는 컴포넌트의 생명주기 동안 변경될 수 있다. 컴포넌트의 상태가 변경되면 React는 자동으로 컴포넌트를 렌더링하여 변경된 데이터를 화면에 반영한다.
함수형 컴포넌트에서 useState라는 hook을 통해 사용할 수 있다. 유동적인 데이터를 다룰 때 사용하고, 컴포넌트 내에서 직접 데이터를 변경할 수 있다.
useState는 State 변수의 초기값을 설정하여 호출하며, 결과값으로 배열을 반환한다. 반환된 배열에서 이전에 설정한 초기값이 할당된 변수와 해당 변수를 수정하기 위한 Set함수가 포함되어 있다.
const [데이터 초기값, 데이터를 수정할 set함수] = useState(초기값);
useState를 사용하여 할당받은 변수는 불변값이다. 직접 수정이 불가능하며 값을 변경하기 위해서 Set함수를 사용해야 한다.
cosnt Count = () => {
cosnt [count, setCount] = useState(0);
return (
<button
onClick={() => setCount(count + 1)}
>+</button>
)
}
Props vs State
Props와 State의 주요 차이점을 다음과 같이 정리해봤다.
Props | State | |
변경 가능성 | 읽기전용 | Set함수로 변경 가능 |
소유자 | 부모 컴포넌트 | 컴포넌트가 소유 및 관리 |
렌더링 | 고정된 데이터를 나타냄 | 상태가 변경될 떄 마다 다시 렌더링 |
Props는 상위 컴포넌트에서 하위 컴포넌트로 데이터를 전달할 때 사용하며, 고정된 데이터를 표시하는 경우 사용한다.
State는 변경 가능한 데이터를 관리하거나 사용자의 상호작용으로 동적으로 데이터를 구현할 때 사용한다.
Context API
여러 컴포넌트 간에 데이터를 전달하려고 할때, 컴포넌트를 여러번 거쳐야 하는 경우 Props를 여러번 작성해주어야 한다. 이는 유지보수를 어렵게 만들고 가독성이 매우 좋지 않다. Context는 이를 해결하기 위해 도입된 기능이다. Context를 사용해 컴포넌트 트리 전체에 데이터를 전달할 수 있다. 중간 컴포넌트를 거치지 않기 때문에 필요한 부분에 부분적으로 사용할 수 있다.
E 컴포넌트에서 사용되서 G 컴포넌트에 Props를 넘겨준 데이터를 J 컴포넌트에서 사용하려 할때, Props 끌어올리기를 사용하면 다음과 같은 상태로 사용해야 한다.
Root 컴포넌트에서 부터 A => C => E => G 까지 4단계 걸쳐 props를 전달해주는 비효율적인 구조를 가질 수 있다.
React에서 Flux라는 개념을 도입해 Context API를 제공하여 이러한 문제를 해결할 수 있다.
Context는 부모 컴포넌트로 부터 자식 컴포넌트로 전달되는 Props 데이터 전달 흐름과 관계없이 전역적인 데이터를 다룰 때 사용한다. 데이터를 Context에 저장후, 필요한 컴포넌트에서 해당 데이터를 가져와 사용할 수 있다.
Context에 저장된 데이터를 사용하기 위해서 Provider와 Consumer를 사용해야 한다. 공통 부모 컴포넌트에 Context의 Provider를 사용하여 데이터를 제공하고, 데이터를 사용하려는 컴포넌트에서 Context Consumer를 이용하여 데이터를 사용한다.
Context API 사용법
createContext 함수를 사용하여 새로운 Context를 생성한다.
import React, { createContext, useContext } from 'react';
const MyContext = createContext();
Context Provider 컴포넌트를 사용하여 데이터를 제공한다. 이 컴포넌트로 전역 상태를 관리하고 자식 컴포넌트에 데이터를 전달한다.
function MyProvider({ children }) {
const data = '전역 데이터.';
return (
<MyContext.Provider value={data}>
{children}
</MyContext.Provider>
);
}
useContext hook을 사용하여 Context의 값을 읽어올 수 있다.
function MyComponent() {
const contextData = useContext(MyContext);
return <div>{contextData}</div>;
}
전역상태를 제공할 최상위 컴포넌트를 Provider 컴포넌트로 감싼다.
function App() {
return (
<MyProvider>
<MyComponent />
</MyProvider>
);
}
import React, { createContext, useContext } from 'react';
const ThemeContext = createContext(); // Context를 생성한다.
function ThemeProvider({ children }) { // Provider를 생성한다.
const theme = 'light';
return (
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>
);
}
function ThemeComponent() {
const theme = useContext(ThemeContext); // useContext로 데이터를 사용한다.
return (
<div>
<p>현재 테마: {theme}</p>
</div>
);
}
function App() {
return (
<ThemeProvider>
<ThemeComponent /> // Context 데이터를 사용할 컴포넌트를 Provider 컴포넌트로 감싼다.
</ThemeProvider>
);
}
export default App;
ThemeProvider에서 테마정보를 전역으로 관리하고 ThemeComponent에서 테마정보를 사용한다.
자주 사용되는 데이터가 2개인 경우 두가지를 모두 제공할 수 있도록 구성할 수 있다.
function Content() {
return (
<ThemeContext.Consumer>
{theme => (
<UserContext.Consumer>
{user => (
<ProfilePage user={user} theme={theme} />
)}
</UserContext.Consumer>
)}
</ThemeContext.Consumer>
);
}
출처
https://legacy.reactjs.org/docs/context.html#consuming-multiple-contexts
'TIL' 카테고리의 다른 글
[React] API 호출함수 관심사의 분리 (0) | 2023.08.27 |
---|---|
[React] useMemo와 useCallback + React.memo (0) | 2023.08.07 |
[Web] LocalStorage SessionStorage Cookie (0) | 2023.08.06 |
[React] Virtual DOM (0) | 2023.07.27 |
브라우저 렌더링 과정에 대해 알아보자 (0) | 2023.07.26 |