본문 바로가기
📗 React

[React] ReactHooks & Context API 를 이용한 state 관리 ( VS Redux)

by Tamii 2021. 5. 4.
반응형

 

📌 React의 상태관리는 어떻게 진행되고 있었나?

 

React 에서 서로 다른 component를 연결하는 방법은 props drilling 이다 .

top레벨의 components에서  bottom레벨의 components 에겟 속성을 전달해야 한다.

 

 

 < 실제 TodoList 프로젝트 당시 props drilling 상황 

 

Atomic design 패턴을 고려하여 만든 프로젝트를 진행할 당시

* TodoList Column을 누르면 popup이 나오고 

* 그 안 (의안의안)의 Buton을 누르면 popup이 닫히는 동작을 작동시킬때 

 

popup  state를 끌고끌고 들어가야 했다... 

 

 

 

 

이걸 해결하기 위해서는⭐️ global state가 모든 components에게 존재해야 한다.

그 깊이가 깊든 관계가 복잡하든 간에 말이다. 이런 문제를 해결하기 위해 나온것이 Redux 빠밤.

 


📌 Redux의 등장 

더보기

React의 상태관리 라이브러리 

Redux는 상태변화 로직이 들어있는 스토어를 통해 원하는 component에 state와 함수를 직접 주입한다.

Redux의 사용을 위해 필요한 funciton들 : actions, reducers, store...

 

REact application의 상태관리가 좀더 용이하지만,

리덕스를 사용하기 위해선 무거운코드복잡한 환경이 조성된다.

 

 

⚠️ 이와 다르게 useContextd API 나 React Hooks는 그렇지 않다.

라이브러리, 폴더 다운로드가 불필요하고 좀더 직접적으로 global state를 관리할 수 있다.

 


 

📌 Context API 

React Context는 React 16.3 부터 React components 에서 global함을 가질 수 있게 되었다.

 

React 공식문서 

"Context는 props는 단계별로 전달하는 과정 없이 component에게 data 를 전달한다 "

 

context 사용법

import React from 'react';

const newContext = React.createContext({ color: 'black' });

const { Provider, Consumer } = newContext;

<Provider value={color: 'blue'}>
  {children}
</Provider>

<Consumer>
  {value => <span>{value}</span>}}
</Consumer>

newContext 는 Provider과 Consumer을 객체로 반환한다.

 

Provider component

component의 깊이와 계층에 관계없이 모든 자식 component의 state를 만들 수 있다.

 

Consumer component

Provider에게서 받은 data를  props drilling없이 소비한다.

 

 


 

📌React Hooks

React Hooks 은 기존의 class 기반의 component환경인 React에서 class 가 아닌

functional component환경을 만들고  함수 기반의 상태(state)관리를 가능하게 한다. 즉 함수형 프로그래밍이 가능하게 만들어줌 

 

원래 Context API를 사용하려면 내용들을 다

Consumer안에 감싸고 state 접근 시 함수를 거쳐야 했다.{value => <span>{value}</span>}}

 

 

useContext

useContext에서는 state에 접근하기 위해 context를 만든다

const newContext = React.createContext({ color: 'black' });

const value = useContext(newContext);

console.log(value); // this will return { color: 'black' }

useContext를 사용하여 state접근시 Consumer로 감싸지 않고도 쉽게  state에 접근 가능해졌다.  => value 만 있으면 됨! 😆

 


 

useReducer

 

useReducer은 React 16.8에서 등장했는데  JS의 reduce함수와 같달까?

useReducer은 reducer function , initial state  값을 받아 => new state를 반환

reducer funciton => new state
initial state
const [state, dispatch] = useReducer((state, action) => {
  const { type } = action;
  switch(action) {
    case 'action description':
      const newState = // do something with the action
      return newState;
    default:
      throw new Error()
  }
}, []);

dispath 함수 => useReducer가 action을 보고 그 type에 맞는 action을 실행한다. 

 

 


Context API  + useReducer 

지금까지는 ContextAPI와 uesReducer의 활용을 각각 보았는데, 

이제 둘을 결합하여 React의 global state를 관리해 보자  => store.js 라는 파일을 만들어서 관리 할 거!

 

// store.js
import React, {createContext, useReducer} from 'react';

const initialState = {};
const store = createContext(initialState);
const { Provider } = store;

const StateProvider = ( { children } ) => {
  const [state, dispatch] = useReducer((state, action) => {
    switch(action.type) {
      case 'action description':
        const newState = // do something with the action
        return newState;
      default:
        throw new Error();
    };
  }, initialState);

  return <Provider value={{ state, dispatch }}>{children}</Provider>;
};

처음 ContexAPI를 생성할때 

createContesst는 { Provider, Consumer} (state생성 , state 소비)를 만들었지만 

여기서는 Provider만받아 state를 생성하고 useContext를 이용하여 소비할 것 !

 

  state 생성  State 소비
ContextAPI Provider  Consumer
Context API + useReducer Provider useContext로 소비  ( useReducer을 활용한 ) 

 

이로써 dispatch 함수를 이용하여 state를 관리한다!

 

<dispatch  사용 예시 >

 <button onClick = { () => dispatch( { type: " action description" ,}) } > 

 

 

단!! 여기서 사용할 state 를 global하게 관리하고 싶다면 App을 감싸줘야 한다.

 

<index.js >

// root index.js file
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import { StateProvider } from './store.js';

const app = (
  <StateProvider>
    <App />
  </StateProvider>
);

ReactDOM.render(app, document.getElementById('root'));

<Component> 사용 시 

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

const ExampleComponent = () => {
  const globalState = useContext(store);
  console.log(globalState); // this will return { color: red }
};

이제 useContext를 import하여 context가 어떤 component에도 접근이 가능하다

 

 

 

 

 

 

참고:blog.logrocket.com/use-hooks-and-context-not-react-and-redux/

 

React Hooks vs. Redux: Do Hooks and Context replace Redux? - LogRocket Blog

Most would admit Redux is an imperfect solution for state management in React. Using Hooks with the Context API provides a more lightweight alternative.

blog.logrocket.com

 

댓글