리액트 16.3 에 소개된 새로워진 Context API 파헤치기


3월말에 리액트 16.3 이 정식 릴리즈되면서, LifeCycle 몇개도 사라지고 (componentWillMount, componentWillUpdate, componentWillReceiveProps), 기존에 존재하던 Context API 가 새로워졌는데요, 이번 튜토리얼에서는 새로워진 Context API 에 대해서, 한번 자세히 다뤄보도록 하겠습니다.

프로젝트에 사용된 코드는 GitHub Repo 에서 확인 할 수 있습니다.

시작하기

Context 는 주로 어떤 용도로 사용되나요?

주로, 애플리케이션으로 전역적으로 데이터가 사용되야 할 때 사용됩니다. 이를테면 사용자 로그인 정보, 애플리케이션 설정, 테마, 등 여러종류들이 있겠지요. 기존의 Context API 도 전역적으로 데이터를 관리하는 용도로 사용할 수는 있었지만, 사용성이 조금 불편해서 자주 사용되지는 않았습니다. 주로, 라이브러리에서 많이 사용됐었는데, 여러분들이 익숙할만한 라이브러리들 – redux, react-router, styled-components 등이 기존에 이 Context API 를 기반으로 구현이 되어있었습니다. Context API 가 이번에, 단순히 그런 라이브러리에서 사용되는 용도가 아니라, 일반적인 용도로도 사용하기 용이하게끔 업그레이드 되었습니다.

프로젝트 준비하기

create-react-app 으로 프로젝트를 만들어서 Context API 를 사용할 준비를 하겠습니다!

create-react-app context-tutorial

프로젝트를 만들고, 여러분이 좋아하는 에디터로 열고, 개발서버도 실행시키세요.

전역적인 상태 관리

어떠한 상태를 프로젝트에서 전역적으로 사용하려면 어떻게 해야 할까요? 만약에 Redux, MobX 같은 라이브러리를 사용하지 않았다면, 아마 이러한 구조와 비슷하게 구현 해야 할 것입니다.

Root 컴포넌트의 state 에는 value 라는 값이 있고, 이 값을 변경시키는 handleSetValue 라는 함수가 있다고 가정해봅시다. value 라는 값은 컴포넌트 F 와 J 에서 보여주고 있고, 이 값을 변화시키는 이벤트는 컴포넌트 G 에서 발생합니다.

이러한 상황에서는, value 값과 handleSetValue 함수를 props 로 하위 컴포넌트한테 전달해주게 됩니다.

예를 들자면, value 값은 Root => A =>B =>  F, Root => H => J 와 같은 형식으로말이죠. 그리고 handleSetValue 값은 Root => A => B => E => G 이렇게 전달이 되겠지요?

뭐, 그정도야, 라고 생각하면서 props 로 쭈욱 내려주는건 큰 문제가 되지 않지만.. 실제 프로젝트에서는 컴포넌트의 깊이가 더욱 깊을수도있고, 다루게 되는 데이터들도 훨씬 많아질 수도 있어서 이렇게만 하면 유지보수성이 낮아질 가능성이 존재합니다.

그렇기에, 우리는 Redux 나 MobX 같은 라이브러리를 사용하죠. 자, 이제는 이러한 라이브러리 없이도, 새로워진 Context API 를 통하여 글로벌 상태 관리를 꽤나 편하게 할 수 있게 됩니다.

대략적, 이러한 구조로 구현을 할 수 있게 되죠.

더 이상 여러 컴포넌트를 거쳐서 값을 전달해주는것이 아니라, Context 를 통해서 원하는 값이나 함수를 바로 쏴줄 수 있게 됩니다.

컴포넌트 준비하기

우리는 다음과 같은 구성으로, 컴포넌트를 만들어보겠습니다.

App 컴포넌트 내부에 LeftPane 과 RightPane 라는 컴포넌트를 만들고, 한쪽에는 값을 설정시킬 Sends 컴포넌트, 그리고 반대쪽에는 Receives 컴포넌트를 넣어주겠습니다.

그리고, App 에서부터 아래로 props 를 전달하는 것이 아닌, Context 를 통해서 바로 가져와서 사용해보겠습니다.

CSS 클래스 작성하기

컴포넌트 구분을 시각적으로 쉽게 할 수 있도록 스타일을 조금 작성해주겠습니다. 다음 내용을 index.css 에서 작성하세요.

src/index.css

body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
}

.panes {
  display: flex;
}

.pane {
  flex: 1;
  border: 1px solid black;
  padding: 1rem;
  margin: 1rem;  
}

그 다음에, 각 컴포넌트를 만들어주겠습니다. 아직은 Context 연동을 하지 않은 상태입니다.

이번에 만들 컴포넌트들은 모두 src/components 디렉토리에 위치시키세요.

src/components/Sends.js

이 컴포넌트에서는 값을 설정시킬 form 을 만들어주겠습니다.

import React, { Component } from 'react';

class Sends extends Component {

  state = {
    input: ''
  }

  handleChange = (e) => {
    this.setState({ input: e.target.value });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    // 구현 예정
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input value={this.state.input} onChange={this.handleChange}/>
        <button type="submit">설정</button>
      </form>
    );
  }
}

export default Sends;

src/components/Receives

이 컴포넌트에서는 나중에 값을 받아와서 보여줄 것입니다.

import React from 'react';

const Receives = () => {
  return (
    <div>
      현재 설정된 값: 
    </div>
  );
};

export default Receives;

src/components/LeftPane.js

왼쪽에 보여줄 컴포넌트를 만듭니다. 여기선 Sends 를 보여주고,

import React from 'react';
import Sends from './Sends';

const LeftPane = () => {
  return (
    <div className="pane">
      <Sends />
    </div>
  );
};

export default LeftPane;

src/components/RightPane.js

우측에 보여질 컴포넌트에서는 Receives 를 보여줍니다.

import React from 'react';
import Receives from './Receives';

const RightPane = () => {
  return (
    <div className="pane">
      <Receives />
    </div>
  );
};

export default RightPane;

src/App.js

마지막으로는 LeftPane 과 RightPane 을 보여주는 일만 남았습니다.

import React from 'react';
import LeftPane from './components/LeftPane';
import RightPane from './components/RightPane';

const App = () => {
  return (
    <div className="panes">
      <LeftPane />
      <RightPane />
    </div>
  );
};

export default App;

자~ 이제 컴포넌트를 준비하는 작업이 끝났습니다. 브라우저에서 다음과 같은 화면이 나타나는지 확인하세요.

Context 만들기

이번엔 Context 를 만들어보겠습니다! Context 는 createContext 라는 함수를 사용해서 만들며, 이 함수를 호출하면 Provider 와 Consumer 라는 컴포넌트들이 반환됩니다. Provider 는 Context 에서 사용 할 값을 설정할 때 사용되고, Consumer 는 나중에 우리가 설정한 값을 불러와야 할 때 사용됩니다.

src/contexts/sample.js 파일을 만들어서 다음과 같이 Context 를 만들어보세요. 주석을 하나하나 읽어가면서 작성해보시길 바랍니다.

src/contexts/sample.js

import React, { Component, createContext } from 'react';

const Context = createContext(); // Context 를 만듭니다.

// Context 안에는 Provider 와 Consumer 라는게 존재합니다.
// 이 둘은, Context 를 이용하기 위해 필요한 컴포넌트들입니다.
// Consumer 는 나중에 내보내줄 때 편하도록 SampleConsumer 라고 부르도록 설정했습니다.
const { Provider, Consumer: SampleConsumer } = Context; 

// Provider 에서 state 를 사용하기 위해서 컴포넌트를 새로 만들어줍니다.
class SampleProvider extends Component {
  state = {
    value: '기본값입니다'
  }

  // 여기서 actions 라는 객체는 우리가 임의로 설정하는 객체입니다.
  // 나중에 변화를 일으키는 함수들을 전달해줄때, 함수 하나하나 일일히 전달하는 것이 아니라,
  // 객체 하나로 한꺼번에 전달하기 위함입니다.
  actions = {
    setValue: (value) => {
      this.setState({value});
    }
  }

  render() {
    const { state, actions } = this;
    // Provider 내에서 사용할 값은, "value" 라고 부릅니다.
    // 현재 컴포넌트의 state 와 actions 객체를 넣은 객체를 만들어서,
    // Provider 의 value 값으로 사용하겠습니다.
    const value = { state, actions };
    return (
      <Provider value={value}>
        {this.props.children}
      </Provider>
    )
  }
}

// 내보내줍니다.
export {
  SampleProvider,
  SampleConsumer,
};

참고로, Context 는 여러개를 만들 수가 있습니다. 때문에, 여러개의 Context 를 사용 할 때 이름이 겹치지 않고 쉽게 다루기 위해서 위와 같이 Provider 와 Consumer 앞에 prefix 를 설정해주었습니다.

Provider 사용하기

Context 를 프로젝트에 적용하려면, 여러분의 앱을 Provider 로 감싸주어야합니다. App.js 를 다음과 같이 수정하세요.

src/App.js

import React from 'react';
import LeftPane from './components/LeftPane';
import RightPane from './components/RightPane';
import { SampleProvider } from './contexts/sample';

const App = () => {
  return (
    <SampleProvider>
      <div className="panes">
        <LeftPane />
        <RightPane />
      </div>
    </SampleProvider>
  );
};

export default App;

Consumer 사용하기

Consumer 는 컴포넌트에서 Context 를 사용해야 할 때에 사용됩니다.

값 보여주기

Receives 에서 context 안에 있는 값을 보여줘봅시다. 컴포넌트를 다음과 같이 작성해보세요.

src/components/Receives.js

import React from 'react';
import { SampleConsumer } from '../contexts/sample';

const Receives = () => {
  return (
    <SampleConsumer>
      {
        (sample) => (
          <div>
            현재 설정된 값: { sample.state.value }
          </div>
        )
      }
    </SampleConsumer>
  );
};

export default Receives;

그러면 이렇게, 우리가 기존에 설정했던 기본값이 보여질 것입니다.

여기서 JSX 내부에서 { (sample) => ... } 이런식으로 작성해주었는데, 이것은 Render Props 라는 패턴입니다.

우리가 방금 작성한 코드는 비구조화 할당 문법을 사용하면 다음과 같이 작성 할 수도 있답니다

      {
        ({state}) => (
          <div>
            현재 설정된 값: { state.value }
          </div>
        )
      }

준비한 actions 호출하기

이번엔 우리가 기존에 준비했던 actions 를 통해서 값을 변경해보겠습니다. 이번에 컴포넌트를 구현하기 위해선, 단순히 render 에서만 필요한게 아니라, 내부에 있는 메소드에서도 필요로 합니다. 그렇기에 아까전에 했던것처럼 render 에서 Consumer 를 사용하는 형태로 구현하지 않고, SendsContainer 라는 컨테이너 컴포넌트를 추가적으로 만들어서 props 로 필요한 값을 전달하는 방식으로 구현해주겠습니다.

src/components/Sends.js

import React, { Component } from 'react';
import { SampleConsumer } from '../contexts/sample';

class Sends extends Component {

  state = {
    input: ''
  }

  componentDidMount() {
    // :: 초기 값 설정
    this.setState({
      input: this.props.value,
    })
  }
  
  handleChange = (e) => {
    this.setState({ input: e.target.value });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    // :: props로 받은 setValue 호출
    this.props.setValue(this.state.input);
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input value={this.state.input} onChange={this.handleChange}/>
        <button type="submit">설정</button>
      </form>
    );
  }
}

// :: Consumer 를 사용하여 context 값을 전달해준 컨테이너 컴포넌트
const SendsContainer = () => (
  <SampleConsumer>
    {
      ({state, actions}) => (
        <Sends 
          value={state.value}
          setValue={actions.setValue}
        />
      )
    }
  </SampleConsumer>
)

// :: Sends 대신에 SendsContainer 를 내보내줌
export default SendsContainer;

이제 값을 수정 할 수 있을 것입니다!

HoC 를 통해 더 편리한 활용

방금 우리가 Container 를 만들 때 사용했던 로직을, 쉽게 재사용 할 수 있도록 HoC 를 사용한다면, 매우 편리해질 수 있습니다. useSample 이라는 함수를 만들고, 내보내주세요.

src/contexts/sample.js

import React, { Component, createContext } from 'react';

const Context = createContext(); // Context 를 만듭니다.

// Context 안에는 Provider 와 Consumer 라는게 존재합니다.
// 이 둘은, Context 를 이용하기 위해 필요한 컴포넌트들입니다.
// Consumer 는 나중에 내보내줄 때 편하도록 SampleConsumer 라고 부르도록 설정했습니다.
const { Provider, Consumer: SampleConsumer } = Context; 

// Provider 에서 state 를 사용하기 위해서 컴포넌트를 새로 만들어줍니다.
class SampleProvider extends Component {
  state = {
    value: '기본값입니다'
  }

  // 여기서 actions 라는 객체는 우리가 임의로 설정하는 객체입니다.
  // 나중에 변화를 일으키는 함수들을 전달해줄때, 함수 하나하나 일일히 전달하는 것이 아니라,
  // 객체 하나로 한꺼번에 전달하기 위함입니다.
  actions = {
    setValue: (value) => {
      this.setState({value});
    }
  }

  render() {
    const { state, actions } = this;
    // Provider 내에서 사용할 값은, "value" 라고 부릅니다.
    // 현재 컴포넌트의 state 와 actions 객체를 넣은 객체를 만들어서,
    // Provider 의 value 값으로 사용하겠습니다.
    const value = { state, actions };
    return (
      <Provider value={value}>
        {this.props.children}
      </Provider>
    )
  }
}

// :: HoC 를 사용
function useSample(WrappedComponent) {
  return function UseSample(props) {
    return (
      <SampleConsumer>
        {
          ({ state, actions }) => (
            <WrappedComponent
              value={state.value}
              setValue={actions.setValue}
            />
          )
        }
      </SampleConsumer>
    )
  }
}

// 내보내줍니다.
export {
  SampleProvider,
  SampleConsumer,
  useSample
};

자, 그러면 이제 Sends 컴포넌트는 다음과 같이 작성 할 수 있습니다.

src/components/Sends.js

import React, { Component } from 'react';
import { useSample } from '../contexts/sample';

class Sends extends Component {

  state = {
    input: ''
  }

  componentDidMount() {
    // 초기 값 설정
    this.setState({
      input: this.props.value,
    })
  }
  
  handleChange = (e) => {
    this.setState({ input: e.target.value });
  }

  handleSubmit = (e) => {
    e.preventDefault();
    // props로 받은 setValue 호출
    this.props.setValue(this.state.input);
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <input value={this.state.input} onChange={this.handleChange}/>
        <button type="submit">설정</button>
      </form>
    );
  }
}

// useSample 사용
export default useSample(Sends);

그리고, Receives 는 다음과 같이 재작성 할 수 있겠죠.

src/components/Receives.js

import React from 'react';
import { useSample } from '../contexts/sample';

const Receives = ({ value }) => {
  return (
    <div>
      현재 설정된 값: { value }
    </div>
  );
};

export default useSample(Receives);

너무 간단해졌죠~?

Context 가 여러개일땐?

이전에, Context 를 여러개 만들 수도 있다고 말씀드렸었지요? 실제로 여러개를 사용한다면 어떤 형식으로 사용할까요? 한번 또 다른 Context 를 만들어봅시다!

src/contexts/another.js

import React, { Component, createContext } from 'react';

const Context = createContext();

const {
  Provider,
  Consumer: AnotherConsumer
} = Context;

class AnotherProvider extends Component {
  state = {
    number: 1,
  }
  actions = {
    increment: () => {
      this.setState(
        ({ number }) => ({ number: number + 1 })
      );
    }
  }
  render() {
    const { state, actions } = this;
    const value = { state, actions };
    return (
      <Provider value={value}>
        {this.props.children}
      </Provider>
    );
  }
}

function useAnother(WrappedComponent) {
  return function UseAnother(props) {
    return (
      <AnotherConsumer>
        {
          ({ state, actions }) => (
            <WrappedComponent
              number={state.number}
              increment={actions.increment}
            />
          )
        }
      </AnotherConsumer>
    )
  }
}

export {
  AnotherProvider,
  AnotherConsumer,
  useAnother
};

그럼, 이걸 기반으로 카운터 컴포넌트를 만들어볼까요? 우선, App 에서 또 Provider 를 넣어줘야 하는데.. 그렇게 하면 새로운 Context 만들때마다 다음과 같은 형식으로 계속 깊어지는게 맘에들지 않을 수도 있습니다.

return (
  <SampleProvider>
    <AnotherProvider>
      ....
    </AnotherProvider>
  </SampleProvider>
)

배열의 내장함수 reduce 와 리액트 컴포넌트의 createElement 를 활용하여 다음 코드를 작성해보세요.

src/App.js

import React from 'react';
import LeftPane from './components/LeftPane';
import RightPane from './components/RightPane';
import { SampleProvider } from './contexts/sample';
import { AnotherProvider } from './contexts/another';

const AppProvider = ({ contexts, children }) => contexts.reduce(
  (prev, context) => React.createElement(context, {
    children: prev
  }), 
  children
);

const App = () => {
  return (
    <AppProvider
      contexts={[SampleProvider, AnotherProvider]}
    >
      <div className="panes">
        <LeftPane />
        <RightPane />
      </div>
    </AppProvider>
  );
};

export default App;

이렇게 하면, Context 갯수가 많아져도, Provider를 적용하기 위해서 코드의 구조가 깊어질 필요가 없답니다. contexts 를 props 로 전달만 해주면 되죠.

자, 그럼 방금 만든 Context 를 사용해서 Counter 컴포넌트를 구현해봅시다!

src/components/Counter.js

import React from 'react';
import { useAnother } from '../contexts/another';

const Counter = ({ number, increment}) => {
  return (
    <div>
      <h1>{number}</h1>
      <button onClick={increment}>더하기</button>
    </div>
  );
};

export default useAnother(Counter);

다음, App 에서 렌더링해보세요.

src/App.js

import React from 'react';
import LeftPane from './components/LeftPane';
import RightPane from './components/RightPane';
import { SampleProvider } from './contexts/sample';
import { AnotherProvider } from './contexts/another';
import Counter from './components/Counter';

const AppProvider = ({ contexts, children }) => contexts.reduce(
  (prev, context) => React.createElement(context, {
    children: prev
  }), 
  children
);

const App = () => {
  return (
    <AppProvider
      contexts={[SampleProvider, AnotherProvider]}
    >
      <div className="panes">
        <LeftPane />
        <RightPane />
      </div>
      <Counter />
    </AppProvider>
  );
};

export default App;

카운터가 작동하나요?

HoC 를 만드는 함수 만들기

이제 Context API 에 좀 익숙해졌지요? 한가지만 더 해봅시다. 우리가 Context 를 만들 때 마다 HoC 를 작성하는게 귀찮을 수도 있습니다. 또, 같은 Context 를 사용하지만 상황에 따라 다른 props 를 전달해줘야 할 때도 있을 것입니다. 그러한 상황에 도움을 줄 수 있는 함수를 새로 만들어보겠습니다.

src/lib/createUseConsumer.js

import React from 'react';

const createUseConsumer = (Consumer) => (mapContextToProps) => (WrappedComponent) => {
  // mapContextToProps 가 없으면 그냥 context 를 그대로 props 에 전달
  const defaultMapContextToProps = (context) => ({context});

  function UseConsumer(props) {
    return (
      <Consumer>
      {
        context => {
          // context에서 원하는 값 추출
          const contextProps = (mapContextToProps || defaultMapContextToProps)(context);
          return (
            <WrappedComponent
              {...contextProps}
              {...props}
            />
          );
        }
      }
      </Consumer>
    );
  }
  // displayName 설정
  const displayName = WrappedComponent.displayName || WrappedComponent.name || 'component';
  UseConsumer.displayName = `UseConsumer(${displayName})`;
  return UseConsumer;
}

export default createUseConsumer;

그럼, another Context 파일을 다음과 같이 작성해줄 수 있습니다.

src/contexts/another.js

import React, { Component, createContext } from 'react';
import createUseConsumer from '../lib/createUseConsumer';

const Context = createContext();

const {
  Provider,
  Consumer: AnotherConsumer
} = Context;

class AnotherProvider extends Component {
  state = {
    number: 1,
  }
  actions = {
    increment: () => {
      this.setState(
        ({ number }) => ({ number: number + 1 })
      );
    }
  }
  render() {
    const { state, actions } = this;
    const value = { state, actions };
    return (
      <Provider value={value}>
        {this.props.children}
      </Provider>
    );
  }
}

const useAnother = createUseConsumer(AnotherConsumer);

export {
  AnotherProvider,
  AnotherConsumer,
  useAnother
};

이제 useAnother 함수에서는 어떤 값을 props 에 넣어줄 지 정해주는 mapContextToProps 를 필요로 하니, Counter 컴포넌트도 조금 수정해주세요.

src/components/Counter.js

import React from 'react';
import { useAnother } from '../contexts/another';

const Counter = ({ number, increment}) => {
  return (
    <div>
      <h1>{number}</h1>
      <button onClick={increment}>더하기</button>
    </div>
  );
};

export default useAnother(
  ({ state, actions }) => ({
    number: state.number,
    increment: actions.increment
  })
)(Counter);

코드를 저장하고, 기존의 카운터가 제대로 작동하는지 확인해보세요.

정리

이번 튜토리얼을 통해서, 새로워진 Context API 의 사용법도 익히고, 프로젝트에서 충분히 활용하기위한 사용방식도 살펴보았습니다. 이 Context API 의 경우에는, 나온지 얼마안됐기 때문에 아직까지는 뭐 정해진 사용 방식은 없습니다. 페이스북이 만들어준 이 기능을, 각자가 생각하기에 편한 방식으로 사용하는 것 이죠. 아마 사용케이스가 좀 자리 잡힐때까지 기다려야 할 텐데요.. 라고 적어두긴 하겠지만 리액트 생태계에서 언제나 그래왔듯이 고정적인 사용케이스는 없을 것 입니다.

현재 새로운 Context API 기반으로 만들어진 상태 관리 라이브러리는 react-waterfall, react-broadcast 등이 있으니 참고하세요. Context 관련 자료는 awesome-react-context 에서 더 많이 찾아보실 수 있습니다.

여기서 입문자들이 가지고 있을 수 있는 의문, “그럼 리덕스 는 어떻게 되나요?” 라는 생각을 하실 수도 있는데요. 일단, Context API 는 글로벌 상태관리를 조금 더 쉽게 해준다는 것은 사실입니다. 기존에 단순히, 깊은 컴포넌트 구조에서 데이터 전달하는 용도로만 리덕스를 사용했더라면 리덕스를 대체 할 수는 있겠죠. 하지만, 리덕스를 제대로 사용해보신 분들이라면 이미 알고계시겠지만, 리덕스는 단순한 전역적 상태 관리 그 이상의 가치가 있습니다. 액션기반 앱 상태 업데이트 로직 작성부터 시작해서, 미들웨어, 강력한 개발자도구 등에서 큰 차이점이 있죠.

리액트에 이러한 기능이 있다는 것만 잘 알아두시고, 앞으로 필요할 때 유용하게 쓰시면 되겠습니다. 그럼, 앞으로도 즐거운 리액트 개발 되시길 바랍니다.

Reference

  • https://medium.com/dailyjs/reacts-%EF%B8%8F-new-context-api-70c9fe01596b
  • http://blog.isquaredsoftware.com/2018/03/redux-not-dead-yet/
  • Wise

    RightPane.js에서 가 아닌 로 수정 요청합니다.

    • 앗…ㅎㅎ 반영했습니다. 감사합니다.

  • jangji1

    혹시 바뀐 Life cycle 에 관해서도 포스팅 해주실 수 있으신가요?

  • 다들 redux 를 주로 사용하고 있을텐데, 리덕스와 context api를 비교해보면 어떤가요?

  • name ahn

    좋은 글 감사합니다.
    질문이 있습니다.

    useSample HOC에서
    “return function UseSample(props)”의 props는 사용되는 건가요?

  • yonggwan

    어느새 보니까 또 못보던게 생겼네요.. 학습의 늪 ㅜㅜ
    A를 만드는 함수… A를 만드는 함수를 만드는 함수… A를 만드는 함수를 만드는 함수… 인것같아요

    그렇다면 Context api는 Redux를 대체 하기 위하여 나온 건가요?
    아니면 서로 다른 별개의 것이라고 이해 해야 하나요?

    • 결국 리덕스도 Context API 를 사용합니다 ^^
      대체하기 위하여 나온것은 아니에요. 다만 그냥 기존 Context API 가 더 좋아진거죠!

  • free&happy

    리덕스 사용하던 참에 비교하면서 잘 봤네요.

  • 최상현

    질문이 있습니다.
    contextApi를 개발에 적용하여 사용중에 있는데요.

    state = {
    temp1,
    temp2
    }

    state가 두개 있을때
    temp1을 변경해도 temp2를 참조하는 컴포넌트도 새로 렌더링이 되는데요.
    이렇게 되면 하나의 context로 state를 참조하는경우에 많은 부분이 렌더링이 계속 날것 같아서요.
    혹시 변경을 막거나 설정을 추가할 수 있는 부분이 있나요?
    각 컴포넌트 별로 shoupComponentUpdate를 쓰기에는 무리가 있는것 같구요..
    또 위에 있는 mapContextToProps는 그저 prop을 발라내서 사용하는것 뿐인것 같구요..
    혹시 그부분에서 아시는 부분있으면 답변 부탁드립니다.

  • 정호섭

    몇시간전에 댓글을 달았었는데 지금 보니까 댓글이 지워져있네요.. 다시 올려요. 처음에 리액트 코드 작성하실때, ReactDOM.render를 사용하지 않으시고 리액트 DOM을 HTML에 렌더링 하시던데 그게 어떻게 가능한건지 이해가 안갑니다. 설명좀 해주세요. 댓글은 지금 보니까 아까 달았던 글이 스팸처리 된거같은데 저 스팸 아니에요..

  • 김서진

    context api 라는 기능이 react-native 에도 동일하게 적용 되나요??

  • 김용우

    좋은 강의 감사합니다

  • 안피곤

    감사합니다.^^

  • Seungil Jang

    다중 Context 를 사용할때

    위와같이 props 가 있는 경우는 어떻게 해야하나요?

  • YoungSea

    useSample 와 UseSample 문제가 있었네요.. Hook에서 첫문자는 반드시 대문자로 하라고 하네요.. ^^;;;
    따라하기하다가 찾았어요.. ^^