useReducer, useContext in React Hooks(기능과 역할) - 1. useContext

addiescode·2020년 6월 2일
0

UseReducer와 UseContext

목록 보기
1/2

UseContext와 UseReducer를 쓰는 이유는,
전역 상태관리 + 상태와 관련된 모든 로직을 컴포넌트간 이동 제약없이 쓸 수 있게끔 하기위해 쓰인다. Context는 사실 UseReducer의 dispatch함수를 전역변수화시키기위해서만 쓰이지는 않는다. 예를 들자면, 어떤 컴포넌트에 뷰를 만드는 로직과 그 정보들이 담겨있었다면 이 변수들을 하나하나 참조해오는거보다 그룹화시켜 전역변수처럼 쓸 수 있게끔 하기 위해 쓰인다.

예를 들면, 다크모드/일반모드를 만들때 변수들을 하나하나 가져와서 바꿔주는게 아닌 한번에 바꿔주기 위해서도 쓰일 수 있다.

UseContext는 새 context를 생성한 곳에서의 Provider로 감싸준 컴포넌트 안에서만 해당 value (dispatch함수)를 가지고 와줄 수 있다.

실제로 다른 컴포넌트에서 이를 쓰고자 할때는 우선
named export된 Dispatch를 가지고와서 해당 컴포넌트에서 useContext함수안에 이 Dispatch를 넣어주어 사용이 가능하다. 여기서 사용 가능한것은 전역 state와 그에 관련된 로직들이다.

반대로, 리액트는 자식 컴포넌트에서 부모 컴포넌트로 state를 올려주지 못하는 단점이 있는데, (함수를 통해 값 정도만 올려줄 수 있다) 이때 자식컴포넌트에서 부모에서부터 온 Context를 업데이트 하게 만들 수도 있다. 그럴 때는 context를 생성할때 메소드를 보낸다.

참고링크: https://ko.reactjs.org/docs/context.html#updating-context-from-a-nested-component

ThemeContext.js

export const themes = {
  light: {
    foreground: '#000000',
    background: '#eeeeee',
  },
  dark: {
    foreground: '#ffffff',
    background: '#222222',
  },
};

export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {},
});
자식 컴포넌트 ThemeToggleButton.js

import {ThemeContext} from './theme-context';

function ThemeTogglerButton() {
  // ThemeTogglerButton는 context로부터
  // theme 값과 함께 toggleTheme 매서드도 받고 있습니다.
  return (
    <ThemeContext.Consumer>
      {({theme, toggleTheme}) => (
        <button
          onClick={toggleTheme}
          style={{backgroundColor: theme.background}}>
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

export default ThemeTogglerButton;

또한, 하나의 자식컴포넌트에서 여러개의 Context를 구독할 수 도 있다.


//기본값이 light인  ThemeContext

const ThemeContext = React.createContext('light');

// 로그인한 유저 정보를 담는 UserContext
const UserContext = React.createContext({
  name: 'Guest',
});

class App extends React.Component {
  render() {
    const {signedInUser, theme} = this.props;

    // context 초기값을 제공하는 App 컴포넌트
    return (
      <ThemeContext.Provider value={theme}>
        <UserContext.Provider value={signedInUser}>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    );
  }
}

function Layout() {
  return (
    <div>
      <Sidebar />
      <Content />
    </div>
  );
}

// 여러 context의 값을 받는 컴포넌트 (Nesting가능)
function Content() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <UserContext.Consumer>
          {user => (
            <ProfilePage user={user} theme={theme} />
          )}
        </UserContext.Consumer>
      )}
    </ThemeContext.Consumer>
  );
}

0개의 댓글