본문 바로가기

블록체인_9기/🩵 React

51강_230718_React(React Hook함수 - useContext, useReducer, useCallback, useMemo)

728x90

 

 

 

 


useContext

  • react에서 제공해주는 내장 hook 함수이다.
  • 전역 상태 관리를 도와주는 함수이다.

Context?

  • Context 사용 시, 단계마다 일일이 props를 넘겨주지 않고도 컴포넌트 트리 전체에 데이터를 제공할 수 있다.
  • 일반적으로는 데이터를 props에 담아 부모에서 자식으로 전달되지만, context를 사용하면 명시적으로 props를 넘겨주지 않아도 값을 공유할 수 있게된다.

👩‍🏫 Context를 사용하기 위해 알아두어야 할 개념!

createContext(initialValue)

  • context 객체를 생성한다.
  • Provider와 Consumer를 반환한다.
  • 파라미터 initialValue는 Provider를 사용하지 않았을 때 적용할 초기 값을 의미한다.

Provider

생성한 context를 하위 컴포넌트에 전달하는 역할을 한다.

Consumer

context의 변화를 감시하는 컴포넌트이다.

import React, { useContext, createContext, useState } from "react";

// useContext

// createContext : 함수를 호출해서 Global객체 생성. context객체 생성
const Global = createContext();

const Context01 = () => {
  return <Context02></Context02>;
};
const Context02 = () => {
  // Global.Provider value로 전달한 값을 받기 위해 useContext() 매개변수로 Context객채를 전달 해준다.
  const { name, setName } = useContext(Global);
  return (
    <>
      내 이름은 {name}
      <button
        onClick={() => {
          setName("wee2");
        }}
      >
        이름변경
      </button>
    </>
  );
};

// Context : 최상단 부모 컴포넌트
const Context = () => {
  // 부모의 상태변수
  const [name, setName] = useState("wee");

  // 부모의 상태 변수 name과 상태변수 업데이트 함수 setName을 객체의 키값으로 obj객체 선언
  const obj = {
    name,
    setName,
  };
  return (
    // Global.Provider : 전역 상태를 관리할 때 최상단 트리로 감싸주는 컴포넌트
    // value : 정해진 키. 전달할 데이터를 넣어준다. (전역상태)
    <Global.Provider value={obj}>
      <Context01></Context01>
    </Global.Provider>
  );
};

export default Context;

 

 

 


useReducer

  • 공식문서에 state의 대체 함수라고 나와있다.
  • 다수의 하위 값을 복잡한 로직으로 만드는 경우 사용한다.
  • 상태 값을 여러가지 사용할 경우. state보다 reducer를 사용하는 것이 좋다.
  • 이전 상태를 다룰 경우에도 이점이 있다.
  • 사용하는 방법은 reducer와 비슷하다.
  • reducer 함수는 현재 상태(state) 객체와 행동(action) 객체를 인자로 받아서 새로운 상태(state) 객체를 반환하는 함수이다.
    • dispatch 함수는 컴포넌트 내에서 상태 변경을 일으키기 위해서 사용되는데 인자로 reducer 함수에 넘길 행동(action) 객체를 받는다.
    • 행동(action) 객체는 관행적으로 어떤 부류의 행동인지를 나타내는 type 속성과 해당 행동과 괸련된 데이터를 담고 있다.
    • 따라서, 컴포넌트에서 dispatch 함수에 행동(action)을 던지면, reducer 함수가 이 행동(action)에 따라서 상태(state)를 변경해준다.

 

👩‍🏫 useReducer() 패턴

const [<상태 객체>, <dispatch 함수>] = useReducer(<reducer 함수>, <초기 상태>, <초기 함수>)

 

import React, { useReducer } from "react";

// 더하기 뺄샘만 간단하게 구현
const INCREMENT = "INCREMENT";
const DECREMENT = "DECREMENT";

// react에서 제공해주는 내장 hook함수
const Reducer = () => {
  // 상태 초기값
  const init = {
    count: 0,
  };

  // reducer함수. 매개변수로 상태와 액션을 넣어줄 예정(콜백함수)
  const reducer = (state, action) => {
    // type이라는 키 값을 전달받을 거임
    // action 객체에
    // reducer 함수는 반환값이 있어야 하니까 return
    const { type } = action;
    switch (type) {
      case INCREMENT:
        // 이전 상태를 가지고 기능을 작성 한 뒤에 반환값으로 상태를 업데이트 해주면 된다.
        return { ...state, count: state.count + 1 };
      case DECREMENT:
        return { ...state, count: state.count - 1 };

      default:
        return;
    }
  };

  // useReducer함수의 매개변수로 첫 번째 메뉴판, 두 번째 초기값을 전달
  const [state, dispatch] = useReducer(reducer, init);

  return (
    <div>
      지금 count의 상태는 : {state.count}
      <button
        onClick={() => {
          dispatch({ type: INCREMENT });
        }}
      >
        더하기
      </button>
      <button
        onClick={() => {
          dispatch({ type: DECREMENT });
        }}
      >
        빼기
      </button>
    </div>
  );
};

export default Reducer;

 

 

 


useCallback

  • 성능 최적화를 위해 도입된 기법이다.
  • 메모이제이션된 콜백을 반환한다.
    • 함수 자체를 메모이제이션한다. 
    • 메모이제이션??
      • 컴퓨터가 동일한 연산을 반복할 때 이전 연산 값을 메모리에 저장하고 이전 값과 결과가 동일할 때 재사용해 연산의 반복을 제거하는 기법이다.
  • 원하는 때에만 콜백 함수를 생성할 수 있다.
  • 복잡한 연산을 사용하고 그 연산이 동일한 값을 내보내는 경우에 사용한다.

 

👩‍🏫 useCallback() 패턴

const Callback = useCallback(()=>{
	// 콜백 함수를 전달
    }, [
    // 배열을 전달. 이 배열을 callback함수가 주시하는 값이다.
    ]);

 

import React, { useCallback, useState } from "react";

const Collback = () => {
  const [count, setCount] = useState(0);
  const [count2, setCount2] = useState(0);

  // count2의 값이 변해야 count의 값이 변하는 것을 확인할 수 있다.
  // count2의 값이 변해야 메모이제이션 콜백을 반환한다.
  const handleCount = useCallback(() => {
    setCount(count + 1);
  }, [count2]);

  const handleCount2 = useCallback(() => {
    setCount2(count2 + 1);
  }, [count2]);
  return (
    <div>
      <div>
        <h1>첫 번째 카운트 : {count}</h1>
        <p>count2가 변하지 않으면 나도 변하지 않아 매모이제이션 된 콜백이야</p>
        <button onClick={handleCount}>count</button>
      </div>
      <div>
        <h1>두 번째 카운트 : {count2}</h1>
        <button onClick={handleCount2}>count2</button>
      </div>
    </div>
  );
};

export default Collback;

 

 

 


useMemo

  • 메모이제이션 기법을 사용한다.
  • 메모이제이션 값을 반환한다.
    • 함수의 리턴 값을 메모이제이션한다.
  • 특정 값이 변경되었을 때만 입력한 연산을 실행하고, 값이 그대로라면 직전에 연산했던 결과를 그대로 다시 사용하는 방법이다.
import React, { useMemo, useState } from "react";

const Memo = () => {
  const [count, setCount] = useState(0);
  const [count2, setCount2] = useState(0);

  const hancleCount = () => {
    console.log("나 count");
    setCount(count + 1);
    setCount2(count + 1);
  };

  // 컴포넌트의 리렌더링을 관리하고 싶음
  // 부모 컴포넌트가 리렌더링되면 자식 컴포넌트가 리렌더링 되는데
  // 부모 컴포넌트 안에 자식컴포넌트가 무척 많으면 전부 리렌더링 되는데
  // 그럼 페이지 최적화가 되지 않는다.
  const handleCount2 = useMemo(() => {
    console.log("나 count2");
    return count2 + 1;
    // count2를 주시하고 있다가 값이 변하면 새로운 값으로 업데이트된다.
  }, [count2]);
  return (
    <div>
      <p>Memo</p>
      <button onClick={hancleCount}>더하기</button>
      <p>handleCount2 : {handleCount2}</p>
    </div>
  );
};

export default Memo;

 

 

 

 

 

 

728x90