[React] useReducer, contextApi

    728x90
    반응형

     

    반응형

     

     

    [React] useReducer, contextApi

    간단한 프로젝트에서 redux, recoil같이 상태관리 라이브러리말고,

    리액트에서 제공해주는 것으로 전체 상태관리를 할 수 없을까? 라는 질문에

    useReducer와 contextApi가 있습니다.

     

     

    useReducer

    • React의 Hook 중 하나로, 복잡한 컴포넌트의 상태 관리하는 데 사용됩니다. 상태 관리 훅
    • 특히 여러 하위 값이 있는 복잡한 정적 로직을 다룰 때나 다음 상태가 이전 상태에 의존적일 때 유용합니다.
    • 이는 Redux의 reducer와 유사한 패턴을 따르며, (state, action) => newState의 형태로 리듀서 함수를 작성합니다.
    • useReducer는 현재 상태(state)와 함께 dispatch 함수를 배열에 넣어서 제공합니다.
    • useReducer는 매개변수로 reducer함수와 initialState(초기값)을 받습니다.
    • dispatch가 새로운 정보를 인자로 받아서 호출하게 되면 --> 기존 state와 새로운정보 (action)을 reducer함수로 전달하게 되고 (매개변수로 전달) --> reducer함수에서 필터해서 새로운 상태로 업데이트 해줍니다.
    • useState의 사용빈도와 각각의 state의 객수를 줄일 수 있다. state가 많아지면 관리가 힘들어진다. 하나의 state, setState로 통일 할 수 있다. 
    import { useReducer } from 'react';
    
    // useReducer의 초기값
    const initialState = {count: 0};
    
    // reducer 함수
    // 현재 상태와 액션객체(바꿀 상태 관련 정보)를 dispatch함수로부터 받아서
    // 필터 후 리턴시켜줍니다. 그러면 상태(state)가 업데이트 됩니다.
    function reducer(state, action) { 
      switch (action.type) {
        case 'increment':
          return {count: state.count + 1};
        case 'decrement':
          return {count: state.count - 1};
        default:
          throw new Error();
      }
    }
    
    function Counter() {
      // useReducer은 reducer함수와 initialState(초기값)을 매개변수로 받습니다.
      // useReducer의 호출 결과로 state(상태 정보)와 dispatch삼수를 배열안에 넣어서 리턴해줍니다.
      const [state, dispatch] = useReducer(reducer, initialState);
      return (
        <>
          Count: {state.count}
          <button onClick={() => dispatch({type: 'decrement'})}>-</button>
          <button onClick={() => dispatch({type: 'increment'})}>+</button>
        </>
      );
    }

     

     

     

     

    contextApi

    • Context API는 React에서 전역적인 데이터(예: 사용자 인증 정보, UI 테마 등)를 관리하는 방법을 제공합니다.
    • Context를 사용하면 컴포넌트 트리를 통해 명시적으로 props를 전달하지 않고도 컴포넌트간에 데이터를 공유할 수 있습니다.
    • props drilling을 해소할 수 있다. (컴포넌트 depth가 깊어질때, props를 전달하게 될때 발생

     

    기존 props drilling

     

    contextApi

     

    1. Context 생성

    // context 생성
    import React, { createContext, useContext } from 'react';
    
    const MyContext = createContext(defaultValue);

     

     

    2. Provider 컴포넌트 사용

    Provider 컴포넌트를 사용하여 하위 컴포넌트에 context의 현재 값을 전달합니다.

    모든 하위 컴포넌트는 이 값을 접근할 수 있습니다.

    // provider 컴포넌트 사용 (context데이터를 공유할 컴포넌트를 묶어준다)
    
    <MyContext.Provider value={/* some value */}>
      {children}
    </MyContext.Provider>

     

     

    3. Context 사용

    Context 값을 사용하고자 하는 컴포넌트에서 useContext 훅을 사용 -> value를 리턴해준다. 이것으로 필요한데 사용.

    // context 사용
    
    const value = useContext(MyContext);

     

     

     

     

     

    같이 사용

    Context와 useReducer 함께 사용하기:

    useReducer와 Context API를 함께 사용하면 전역 상태 관리 로직을 구현할 수 있습니다.

    useReducer로 상태 관리 로직을 처리하고, Context API로 앱의 다양한 부분에 상태를 공유할 수 있습니다.

    const [state, dispatch] = useReducer(reducer, initialState);
    <MyContext.Provider value={{ state, dispatch }}>
      {children}
    </MyContext.Provider>

     

     

     

     

    주의점 (단점)

    • contextApi가 성능최적화하기 되게 힘들다.
    • contextApi를 사용하면 state를 바꿀때 하단의 컴포넌트들 전체가 리랜더링 되기 때문이다.
    • 중요한것은 함수가 리랜더링(재실행되더라도) 거기에서 리턴하는 값은 캐싱 (메모라이징)해두면 성능 최적화에 도움될 수 있다.
    • 그럴때 사용하는 것이, useMemo, React.memo
    • 먼저 전체적으로 React.memo를 통해서 컴포넌트들을 새컴포넌트로 바꿔줘야하는데,
      어느 컴포넌트에 적용시, 하위컴포넌트들에게도 다 적용해야 그 부모격 컴포넌트도 적용된걸로 친다니 주의 해야한다.
    • 리덕스에선 state가 동기적으로 바뀌는데 uesReducer에서는 비동기적으로 바뀐다.
    • 이러한 이유때문에 useReducer, contextApi => 소규모 프로젝트에서 리덕스 대신 사용가능, 이둘만으론 비동기 작업할때 불편, 흉내는 낼 수있음
    • redux = 규모가 큰 앱에선 사용할수밖에 없다
    // useMemo 사용 예시
    
    const value = useMemo(() => { // useMemo
        return {
            tableData,
            halted,
            dispatch,
        };
    }, [tableData, halted]); // 의존성 배열에 필요로 하는 값들 넣어주기 
    
    return (
        <>
            <TableContext.Provider value={value}>
                <h1>지뢰찾기</h1>
                <Form />
                {timer + "초"}
                <div></div>
                <Table />
                <div>{result}</div>
            </TableContext.Provider>
        </>
    );

     

     

     

     

     

    useReducer가 Flux 패턴?

    useReducer는 React에서 사용하는 Flux 패턴의 아이디어를 기반으로 하는 Hook입니다.

    Flux 패턴은 애플리케이션의 데이터 흐름을 단방향으로 유지하는 아키텍처 패턴으로,

    Facebook에 의해 처음 소개되었습니다.

    Flux 패턴의 단방향 데이터 흐름을 반영하며, 애플리케이션 상태 관리를 보다 예측 가능하게 만듭니다.

     

    Flux 패턴의 주요 구성 요소

    1. Dispatcher: 모든 데이터 흐름을 관리하는 중앙 허브입니다.
    2. Stores: 애플리케이션의 상태(state)와 로직을 보유합니다.
    3. Actions: 상태를 변경하기 위해 보내는 데이터 패킷입니다.
    4. Views: 데이터를 표시하고 사용자 입력을 처리하여 Actions를 발생시킬 수 있는 React 컴포넌트입니다.

     

    useReducer와 Flux의 관계

    useReducer는 이러한 Flux 패턴의 핵심 원칙 중 일부를 반영합니다:

    • Reducer: Flux에서의 Store와 유사한 역할을 합니다. Reducer는 현재 상태와 액션 객체를 받아 새 상태를 반환하는 순수 함수입니다. 이 과정에서 "reducing function"이라고 불리며, 이는 입력된 상태를 액션에 따라 새 상태로 "축소(reduce)"합니다.
    • Action: 상태 변화를 일으키는 이벤트를 설명하는 객체입니다. Flux에서와 마찬가지로, useReducer에서도 액션은 상태 변화를 위해 리듀서에 전달됩니다.
    • Dispatch Function: useReducer에서 리듀서 함수를 호출하는 함수입니다. 이 함수는 액션 객체를 인자로 받아 상태를 업데이트하는데 사용됩니다. 이는 Flux의 Dispatcher 역할을 일부 수행합니다.

     

     

     

     

     

     

     

     

     

    참조!

    https://velog.io/@apro_xo/React.js-context-APIFeat.-useContext

     

    [React.js] context API(Feat. useContext)

    context API(Feat. useContext)

    velog.io

     

     

    728x90
    반응형

    댓글