YeonjuOHYE / javascript

0 stars 0 forks source link

react context #10

Open YeonjuOHYE opened 5 years ago

YeonjuOHYE commented 5 years ago

Context

왜 사용?

전역적으로 사용하는 값들 prop으로 전달할 필요 없이 필요할 때 바로바로 사용할 수 있도록 (I feel it's like static?)

Context 객체 만들기

const MyContext = React.createContext(defaultValue);

Context.Provider

<MyContext.Provider value={/* 어떤 값 */}>

Class.contextType

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* MyContext의 값을 이용한 코드 */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* ... */
  }
}
MyClass.contextType = MyContext;

※ 위 방법은 하나의 context만을 구독할 수 있다. 여러 context를 구독하는 방법은 아래에 정리해 놓을 테니 필요할 때 찾아서 봐라

Context.Consumer

Class.contextType 을 함수 컴포넌트에서 사용할 떄 쓴다.

import React, { useState, useEffect } from "react";
import logo from "./logo.svg";
import "./App.css";

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

export const ThemeContext = React.createContext(themes.dark);

class ThemeButton extends React.Component {
  render() {
    let props = this.props;
    let theme = this.context;
    return <button {...props} style={{ backgroundColor: theme.background }} />;
  }
}

ThemeButton.contextType = ThemeContext;

function Toolbar(props) {
  return <ThemeButton onClick={props.changeTheme}>Change Theme</ThemeButton>;
}

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      theme: themes.light
    };

    this.toggleTheme = () => {
      this.setState(state => ({
        theme: state.theme === themes.dark ? themes.light : themes.dark
      }));
    };
  }

  render() {
    return (
      <div>
        <ThemeContext.Provider value={this.state.theme}>
          <Toolbar changeTheme={this.toggleTheme} />
        </ThemeContext.Provider>
        <ThemeButton />
      </div>
    );
  }
}

export default App;

하위 컴포넌트에서 context 업데이트 하기

import React, { useState, useEffect } from "react";
import logo from "./logo.svg";
import "./App.css";

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

export const ThemeContext = React.createContext({
  theme: themes.dark,
  toggleTheme: () => {}
});

function ThemeToggleButton() {
  return (
    <ThemeContext.Consumer>
      {({ theme, toggleTheme }) => (
        <button
          onClick={toggleTheme}
          style={{ backgroundColor: theme.background }}
        >
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggleTheme = () => {
      this.setState(state => ({
        theme: state.theme === theme.dark ? themes.light : themes.dark
      }));
    };

    this.state = {
      theme: themes.light,
      toggleTheme: this.toggleTheme
    };
  }

  render() {
    return (
      <ThemeContext.Provider value={this.state}>
        <Content />
      </ThemeContext.Provider>
    );
  }
}

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

export default App;