React 와 context

JJ_Dean·2023년 1월 4일
0

React

목록 보기
14/14
post-thumbnail

context란?

프롭 체인 없이, 리액트 내부적으로 state를 관리할 수 있게 해준다.
어떠한 컴포넌트든 state에 접근하여 저장된 내용을 바꾸고, 다른 컴포넌트들에도 수정사항을 전달할 수 있게 한다.

위 그림처럼 App.js 에서 header.js 를 import 하여 사용하고, header.js 에서 navigation.js 를 import 하여 사용한다고 가정하자.

지금까지는 프롭 체인을 통해 state를 부모 컴포넌트에서 자식 컴포넌트로 전달하여 사용할 수 있었다. 반대로 state 끌어올리기도 가능했다. 하지만 이 방법은 컴포넌트 간의 props 가 끊임없이 전달되지 않으면 사용할 수 없었다.

그래서 위 그림처럼 comtext 라는 개념으로 필요한 state 를 언제든지 어떤 컴포넌트에서도 호출하고 수정할 수 있게 만들었다고 생각한다.

장점

  • 코드가 간결해진다.

만약 많은 정보들을 자식의 자식 컴포넌트에 props로 보내고 싶다면 자식 컴포넌트에서 또 그 자식 컴포넌트로 정보들을 일일이 props로 보내줘야 한다. 이럴때 context를 이용하면 코드가 간결해질 수 있다.

사용해보자

auth-context.js 생성

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

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

export default AuthContext;

auth-context.js 라는 파일을 만들었다.
일반적인 컴포넌트와는 다르게 React.createContext로 만들어진다. 컴포넌트는 아니지만 컴포넌트의 역할을 한다.
이 AuthContext는 데이터를 담은 객체를 갖는데, 초기값으로 'isLoggedIn: false' 와 'onLogout: () => {}' 을 가진다. 이후 이 context를 공급하는 곳에서 초기값을 다시 변경해줄 수 있다.
onLogout의 값으로 더미 함수를 넣는 이유는 공급처에서 다시 데이터 객체 작성할 때, IDE 자동 완성을 편하게 하려고 작성했다.

App.js에서 Provider 생성

// App.js
import React, { useState } from 'react';

import AuthContext from './auth-context';
import Header from './Header'

fucntion App () {
  const [isLoggedIn, setIsLoggedIn] = useState(false);
  
  const logoutHandler = () => {
    console.log('로그아웃 됐습니다.')
  }
  
  return (
    <AuthContext.Provider value={{
      isLoggedIn: isLoggedIn,
      onLogout: logoutHanlder
    }}>
    
    <Header /> 
    // Header.js 의 JSX 코드 안에 navigation 컴포넌트가 들어있다.
    
    </ AuthContext.Provider>
}  

App.js에서 AuthContext를 import 하고, Provider로 모든 요소들을 감싸줬다. 이때 value={} 으로 초기값을 다시 설정해주었다. 위해서 더미 함수를 넣어준 덕분에 IDE에서 자동완성이 가능했다.

이 Provider는 App.js의 모든 후손 컴포넌트들이 AuthContext의 state를 읽고, 쓰기를 가능하게 한다.

이제 이 공급받은 state를 후손의 후손 컴포넌트인 navigation.js에서 사용해보자.

// navigation.js
import React from 'react';

import AuthContext from './auth-context';

const navigation = () => {
  return (
    <AuthContext.Consumer>
    {(ctx) => {
      <div>
    	{ctx.isLoggedIn && (
         <div>로그인 상태일 때 보이는 요소</div>
         )}
      </div>
    }}
    </AuthContext.Consumer>
  )
}

공급(Provide)이 있었으니 소비(Comsume)할 차례이다.
모든 요소들을 AuthContext.Consumer로 감싸주었다. 그리고 JSX 코드 안에서 자바스크립트 구문을 사용하듯이 중괄호 안에 파라미터 값(ctx)를 갖는 익명 함수를 선언한다. 이제 AuthContext 에서 만들고 App.js 에서 수정한 state를 이 자손의 자손 컴포넌트에서 사용할 수 있다.
state 값을 가져오기 위해 ctx.isLoggedIn 처럼 파라미터로 받은 ctx를 통해 참조할 수 있다.

이제 이 방법보다 조금 더 간편한 방법을 사용해보자.

useContext 훅 사용하기

useContext는 React에서 지원하는 훅(Hook) 이다. 위에서 이용한 AuthContext를 사용하기 쉽게 해주는 녀석이다.
바로 써보자

// navigation.js
import React, { useContext } from 'react';

import AuthContext from './auth-context';

const navigation = () => {
  
  const ctx = useContext(AuthContext); // useContext 사용
  
  return (
    <div>
      {ctx.isLoggedIn && (
         <div>로그인 상태일 때 보이는 요소</div>
      )}
    </div>
  )
}

위에서 Consumer를 통해 받아온 것보다 훨씬 코드가 깔끔해졌다.
위에서 동작하는 것과 똑같이 아주 똑같이 동작한다.

한계

useContext는 props를 대체할 수 있어 보인다. 아쉽지만 그렇지 않다.
짧은 시간동안 여러번 바뀌는 state 나 재사용해야 하는 컴포넌트에서는 useContext의 사용이 권장되지 않는다.

profile
공부하고 내 것으로 만들자.

0개의 댓글