React

[React Hook] useContext 사용하기

hazel__ 2022. 5. 22. 01:37

React context는 상태를 전역적으로 관리할 수 있다.

 

하위 컴포넌트에 props로 인자를 전달하는 경우, 값을 사용하지 않는 컴포넌트라도 전달의 목적으로 값을 전달해야 한다.

context를 사용하여 상태관리를 더 효율적으로 관리할 수 있다.

 

useContext는 useState 를 함께 사용하여 구현할 수 있다.

 

nested 되어 props로 변수를 전달하는 경우는 아래 코드와 같다.

//Nested.js

export const Nested = (props) => {
  return (
    <>
      <div>Nested</div>
      <Component value={props.value}></Component>
    </>
  )
}

const Component = (props) => {
  return (
    <>
      <div>Component</div>
      <Component2 value={props.value}></Component2>
    </>
  )
}

const Component2 = (props) => {
  return (
    <>
      <div>Component2</div>
      <div>{props.value[0]}</div>
      <button onClick={()=>props.value[1](props.value[0] + '!')}>BUTTON</button>
    </>
  )
}
//App.js
function App() {
  const value = useState("!NESTED!");

  return (
    <Nested value={value}></Nested>
  )
}

 

이때 결과는 아래와 같다.

nested

 


 

context

이를 context를 사용하여 분리해보자!

//Divided.js
export const Divided = () => {
  return (
    <>
      <div>Divided</div>
      <Component></Component>
    </>
  )
}

const Component = () => {
  return (
    <>
      <div>Component</div>
      <Component2></Component2>
    </>
  )
}

const Component2 = () => {
  const value = useContext(ValueContext);
  return (
    <>
      <div>Component2</div>
      <div>{value[0]}</div>
      <button onClick={()=>value[1](value[0] + '!')}>BUTTON</button>
    </>
  )
}
//App.js
export const ValueContext = createContext();

function App() {
  const value = useState("!NESTED!");

  return (
    <ValueContext.Provider value={value}>
      <Divided></Divided>
    </ValueContext.Provider>
  )
}

 

 

결과 화면

 


Context.Consumer

useContext 훅을 사용하지 않고 적용하려면!

context.Consumer 를 사용하여 변수를 받아올 수 있다.

const Component2 = () => {
  return (
    <ValueContext.Consumer>
      { (value) => (
        <>
          <div>Component2</div>
          <div>{value[0]}</div>
          <button onClick={()=>value[1](value[0] + '!')}>BUTTON</button>
        </>
      )}
    </ValueContext.Consumer>
  )
}

 


useReducer

useReducer 사용하기!

reducer를 먼저 만든다.

const reducer = (state = '!NESTED!', action) => {
  switch (action.type) {
    case 'PLUS':
      return state + '!';
    case 'MINUS':
      return state.slice(0, -1);
    default:
      return state;
  }
}

action이 PLUS 인 경우, ‘!’를 붙이고, MINUS 인 경우에는 마지막 글자를 삭제한다.

 

 

다음으로 App.js를 수정한다!

useState 대신 useReducer로 상태를 관리할 수 있다.

function App() {
  const value = useReducer(reducer, '!NESTED!');

  return (
    <ValueContext.Provider value={value}>
      <Divided></Divided>
    </ValueContext.Provider>
  )
}

useState 에서 value[0] 은 value 값, value[1]은 set 함수라면,

useReducer에서는 value[0]은 value 값, value[1]은 dispatch 함수이다.

 

 

마지막으로 컴포넌트를 수정하자~

context.Consumer와 useContext 둘 다 사용가능하다.

다만, set 함수와는 다르게 dispatch 함수에는 type을 정의해야 한다.

const Component2 = () => {
  return (
    <ValueContext.Consumer>
      { (value) => (
        <>
          <div>Component2</div>
          <div>{value[0]}</div>
          <button onClick={()=>value[1]({type:'PLUS'})}>PLUS</button>
          <button onClick={()=>value[1]({type:'MINUS'})}>MINUS</button>
        </>
      )}
    </ValueContext.Consumer>
  )
}
const Component2 = () => {
  const value = useContext(ValueContext);
  return (
    <>
      <div>Component2</div>
      <div>{value[0]}</div>
      <button onClick={()=>value[1]({type:'PLUS'})}>PLUS</button>
      <button onClick={()=>value[1]({type:'MINUS'})}>MINUS</button>
    </>
  )
}