Context API에 대해 알아보자

Heebeom·2023년 5월 24일
0

React 완벽 가이드

목록 보기
5/6
post-thumbnail

Context API란?

context를 이용하면 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있습니다.

일반적인 React 애플리케이션에서 데이터는 위에서 아래로 (즉, 부모로부터 자식에게) props를 통해 전달되지만, 애플리케이션 안의 여러 컴포넌트들에 전해줘야 하는 props의 경우 (예를 들면 선호 로케일, UI 테마) 이 과정이 번거로울 수 있습니다. context를 이용하면, 트리 단계마다 명시적으로 props를 넘겨주지 않아도 많은 컴포넌트가 이러한 값을 공유하도록 할 수 있습니다.

React 공식 문서 - Context 발췌.

React 공식 문서에 따르면, 데이터를 Props로 넘기는 대신, 간편하게 데이터를 컴포넌트 전체에 제공할 수 있는 기능이라고 한다. 한번 예시를 들어 알아보자.

  • 가상의 React Component 구조를 살펴보자. MyPage 컴포넌트는 LoginForm의 LoginState를 참조하려고 한다.
  • LoginForm에서 MyPage까지 LoginState를 전달하기 위해, props 체인과 handler 함수를 사용해 최상위 앱인 APP까지 전달한 뒤, State를 MyPage에 prop으로 전달하면서 매우 긴 Prop Chain이 발생하였다.

  • Context API를 사용하면 긴 Prop Chain 대신, 직접 State를 전달할 수 있다.
  • 개발자 입장에서 훨씬 간결하고, 유지보수가 쉽다.

Context API를 사용해보자

Context를 선언하자

// store/auth-context.js
import React from 'react';

const AuthContext = React.createContext({
    isLoggedIn: false,
    onLogout: () => {},
    onLogin: (email, password) => {},
});

export default AuthContext;
  • createContext 함수로 선언할 수 있다. 인자는 context의 기본값을 받으며, 대부분 Object를 사용한다. (상태가 복잡하지 않을 때, string으로 써도 무방하다).)

Context를 App에 알려주자

Provider 작성하기

// store/auth-context.js
export const AuthContextProvider = (props) => {
    const [isLoggedIn, setIsLoggedIn] = useState(false);

    const logoutHandler = () => {
        localStorage.setItem('isLoggedIn', '0');
        setIsLoggedIn(false);
    }

    const loginHandler = () => {
        localStorage.setItem('isLoggedIn', '1');
        setIsLoggedIn(true);
    }

    return (
      <AuthContext.Provider
      value={{ 
        isLoggedIn: isLoggedIn,
        onLogout: logoutHandler,
        onLogin: loginHandler,
      }}>
          {props.children}
      </AuthContext.Provider>
    );
}
  • 이제 "이 Context를 이러한 Component에서 사용하고 싶습니다." 라고 React에 알려줘야 한다.
  • AuthContext.Provider 컴포넌트를 활용해, 사용할 Component를 감싸면 된다.
  • State 관리 Logic을 사용하는 컴포넌트에 작성해도 되지만, 이렇게 따로 Provider를 정의하고, 사용하는 Logic를 모아두면 훨씬 깔끔하다.

사용할 컴포넌트 상위에 감싸기

// index.js
import { AuthContextProvider } from './components/store/auth-context';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <AuthContextProvider>
        <App />
    </AuthContextProvider>
);
  • APP 전체를 내가 작성한 Provider로 감쌌다. 이제 App 전체에서 AuthContext에 접근할 수 있다.
  • 만약 Context를 국소적인 부분에서만 참고한다면, 그 부분만 감싸면 된다.

Context 값을 사용하자


const Navigation = (props) => {
  const context = useContext(AuthContext);
  
  ...
  
  return (
    ...
    {context.isLoggedIn && ( // context의 boolean값에 접근하였다.
      <li>
         <a href="/">Users</a>
      </li>
    )}

    {context.isLoggedIn && (
      // 값 뿐만이 아니라, Context는 함수도 제공해줄 수 있다.
      <button onClick={context.onLogout}>Logout</button>
    )}
  );
  • useContext 함수로 Context에 접근할 수 있다. 이 때, 인자로 '접근할 Context'를 지정해 주자.
  • useContext가 반환한 context에 상수를 통해, AuthContext에 접근할 수 있다.

무조건 Context를 사용하는게 좋을까?

Context는 컴포넌트의 재사용성을 막는다

context의 주된 용도는 다양한 레벨에 네스팅된 많은 컴포넌트에게 데이터를 전달하는 것입니다. context를 사용하면 컴포넌트를 재사용하기가 어려워지므로 꼭 필요할 때만 쓰세요.

React 공식 문서 - Context 발췌.

  • Context 사용은, "매우 특정적인 작업을 수행하는 Component"에만 사용해야 한다.
  • 예를 들어, 여러 상황에서 공통적으로 사용하는 Button Component에 로그인을 위한 Context를 사용하면, 그 버튼은 "로그인만을 위한 버튼"이 되어 버린다.

State 변경이 잦은 경우, 적합하지 않다

  • Context API의 State가 변경될 때, 아래 Component가 전부 re-rendering되는 이슈가 존재한다.
  • 로그인 여부같이 자주 변경되지 않으면 상관없지만, 몇 초마다 바뀌는 state의 경우 Context로 관리하면 App의 성능저하가 발생할 수 있다.
profile
이도저도 아닌 개발자

0개의 댓글