useDebugValue 훅을 사용하면 리액트 개발자 도구에서 어떤 훅을 사용 중인지, 상태 값이 현재 어떤 상태인지 확인할 수 있다.

[React]커스텀 훅의 상태를 추적하는 useDebugValue

 

[React]커스텀 훅의 상태를 추적하는 useDebugValue

 

1. useDebugValue는 무엇인가?

2. 사용법

추천글

 

1. useDebugValue는 무엇인가?

 리액트 개발자 도구를 통해 커스텀 훅의 상태를 확인할 수 있는 훅이다.

 console.log()를 사용할 때와의 차이
  • 디버깅만을 위한 훅 사용으로 코드를 직관적으로 표현할 수 있다.
  • 로그가 개발자 도구에 남기 때문에 콘솔이 깔끔해진다.

2. 사용법

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

function useCount() {
  const [count, setCount] = useState(0);

  useDebugValue(count, (count) => `현재 카운트: ${count}`);

  const addCount = () => {
    setCount(count + 1);
  };

  return [count, addCount];
}

function App() {
  const [count, addCount] = useCount();

  return (
    <div>
      {count}
      <button onClick={addCount}>숫자 변경</button>
    </div>
  );
}

export default App;


hooks 탭에서 useDebugValue 훅으로 작성한 코드 확인 가능

추천글

리액트 공식문서 - useDebugValue

'react > ' 카테고리의 다른 글

[React] 렌더링이 되기 전 코드를 실행하는 useLayoutEffect  (0) 2024.04.29

 useLayoutEffect는 useEffect와 달리 렌더링이 되기 전 실행되어 그 결과를 렌더링에 반영한다. 또한 useLayout Effect의 콜백함수는 모두 동기적으로 실행된다는 것이 차이점이다.

[React] 렌더링이 되기 전 코드를 실행하는 useLayoutEffect

 

[React] 렌더링이 되기 전 코드를 실행하는 useLayoutEffect

 

1. useLayoutEffect는 무엇인가?

2. 언제 사용하는가

추천글

 

1. useLayoutEffect는 무엇인가?

 useLayoutEffect는 useEffect와 유사한 역할을 하는 react 훅이다.

공통점
  • 의존성 배열: 콜백 함수와 의존성 배열을 이용해 특정 상태가 변경될 때 수행할 작업을 지정할 수 있다.

차이점

  • 렌더링 차단 여부: useLayoutEffect는 모든 작업이 끝날 때까지 렌더링이 일어나지 않는다. 따라서 실행시간이 길면 렌더링도 지연된다.
  • 실행시점: useLayoutEffect는 렌더링 전에 실행된다. useEffect는 렌더링 이후에 실행된다.

2. 언제 사용하는가

import React, { useState, useEffect, useLayoutEffect, useRef } from "react";

function App() {
  const contentRef = useRef(null);
  const [tooltipLeft, setTooltipLeft] = useState(0);

  useLayoutEffect(() => {
    const contentWidth = contentRef.current.offsetWidth;
    setTooltipLeft(contentWidth);
  }, []);

  useEffect(() => {
    const contentWidth = contentRef.current.offsetWidth;
    setTooltipLeft(contentWidth);
  }, []);

  return (
    <div>
      <span ref={contentRef}>안녕하세요</span>
      <div style={{ position: "absolute", top: 0, left: tooltipLeft }}>
        설명입니다.
      </div>
    </div>
  );
}

export default App;

 돔의 레이아웃에 맞추어 작업을 해야할 때 사용한다. 예를 들어, 특정 요소에 대해 툴팁을 만든다고 가정해보자. 이때 해당 요소에 들어갈 텍스트가 상황에 딸 다르다면, 그때마다 요소의 크기를 측정해 툴팁의 x, y 좌표를 지정해야 한다. 이러한 경웨 useLayoutEffect를 사용한다면 요소를 렌더링 하기 전 요소의 크기를 측정하고 툴팀의 레이아웃을 지정할 수 있게 된다.
 다만 작업을 모두 동기적으로 실행하고 그동안 렌더링도 지연된다는 점에서 무분별하게 사용한다면 프로젝트의 성능이 떨어질 수 있다.

추천글

React 공식문서 - useLayoutEffect

'react > ' 카테고리의 다른 글

[React]커스텀 훅의 상태를 추적하는 useDebugValue  (0) 2024.04.29

리액트 프레임 워크는 가상돔을 활용해, 변경된 부분을 감지하여 효율적인 렌더링이 가능합니다.

[React] 가상돔 알아보기

 

[React] 가상돔 알아보기

 

요약

1. 가상돔이란 무엇이고, 어떻게 작동하는가?

2. 가상돔 적용과정

 

요약

 리액트 프레임워크는 JSX 코드를 분석하여 가상 돔을 생성한다. 만약 상태가 변경되면 이전 가상돔과 비교하여 달라진 부분을 감지하여 리렌더링한다.

1. 가상돔이란 무엇이고, 어떻게 작동하는가?

 브라우저가 HTML을 파싱할 때 생성하는 DOM과 동일한 형태이다. 다만 가상 돔은 실제 돔을 조작하는 것이 아니라, UI의 변경점을 확인하는 용도이다. 리액트 프로젝트가 실행되면 각 컴포넌트의 JSX 코드를 분석하여 리액트 요소를 생성한다. 이 요소들이 결합되어 가상돔을 구성한다.
 상태의 변경이 일어날 시, 이 과정을 반복하여 매번 새로운 가상돔이 생겨난다. 새로운 가상 돔이 생겨난 이후에는 이전의 가상돔과 비교하여 달라진 부분을 파악한다. 해당 부분만 재렌더링 하여, 효율적인 렌더링이 가능케 한다.

2. 가상돔 적용과정

  1. 리액트 프로젝트가 실행되며, JSX 코드를 분석하여 리액트 요소 생성
  2. 리액트 요소 결합하여 가상돔 생성
  3. 상태 변경이 일어남
  4. JSX 코드를 다시 분석하면서 새로운 리액트 요소 생성
  5. 새로운 가상돔 생성
  6. 새로운 가상돔을 직전 가상돔과 비교하여 달라진 부분 감지
  7. 달라진 부분만 재렌더링

redux toolkit을 이용해 전역 상태 관리 코드를 작성하는 법을 알아봅니다. redux toolkit을 사용하면 기존 redux를 좀더 간편하게 이용할 수 있습니다.

 

redux toolkit으로 전역 상태 관리하기

 

 목차

 

1. redux toolkit이란?

2. toolkit을 사용하면 뭐가 달라지나요?

3. 구현 코드

4. 구현된 코드로 보기

함께 보면 좋은 글

 

1. redux toolkit이란?

  • redux를 더 쉽게 사용하고 관리할 수 있게 도와주는 공식 라이브러리
  • 즉, redux를 좀 더 쉽게 사용하기 위한 라이브러리

2. toolkit을 사용하면 뭐가 달라지나요?

  • 코드 간소화
    • 기존 redux는 boilertemplate(기본 코드)가 너무 길다는 단점이 있었음
    • toolkit을 통해 코드를 간략화 할 수 있음

 

  • 불변성 관리
    • 기존 redux에서는 상태 관리 로직에서 불변성 관리가 되지 않아, 기존 값을 따로 복사해야 했음
    • ex) { ...state, name: 홍길동 }
    • toolkit을 사용할 시 불변성 유지가 되기 때문에, 변경하고 싶은 값만 변경하면 됨
    • ex) state.name = "홍길동"

 

  • 개발자 도구 적용 간편
    • toolkit은 redux-devtools를 따로 설치하지 않고, 설정만 해도 적용

3. 구현 코드

  • slice 생성
    • slice는 reducer와 action을 동시에 관리함
    • 초기 상태 값 설정
    • slice 내부에 action 생성 (state의 변경 시키고 싶은 값만 수정)
    • slice를 통해 생성된 action 내보내기

 

// store/slice/infoSlice.js

import { createSlice } from "@reduxjs/toolkit";

// 초기 상태 값 설정
const initialState = { name: "홍길동", age: 20 };

// slice를 통해 action 생성
const infoSlice = createSlice({
  name: "counter",
  initialState,
  reducers: {
    // 액션 생성
    // state의 변경 시키고 싶은 값만 수정
    changeName: (state, action) => {
      state.name = action.payload;
    },

    changeAge: (state, action) => {
      state.age = action.payload;
    },
  },
});

// reducer에 생성한 action export
export const { changeName, changeAge } = infoSlice.actions;
export default infoSlice.reducer;

 

  • store 생성
    • configure 함수 사용
    • reducer 등록
    • 개발자 도구 사용 설정

 

// store/store.js

import { configureStore } from "@reduxjs/toolkit";
import infoReducer from "./slice/infoSlice";

// configureStore 함수 사용
// devTools 따로 설치하지 않고 설정만 해도 사용 가능
const store = configureStore({
  // 생성한 reducer 등록
  reducer: {
    info: infoReducer,
  },
  // 개발자 도구 사용 설정 ON
  devTools: true,
});

export default store;

 

  • 가장 상위 컴포넌트에 store 등록

 

// main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/store";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    {/* 작성한 store 적용 */}
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

 

  • redux 사용하기
    • state 불러오기
    • dispatch 사용하기
    • dispatch를 통해 action을 store로 전달

 

// App.jsx

import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeAge, changeName } from "./store/slice/infoSlice";

function App() {
  // store의 state 불러오기
  const info = useSelector((state) => state.info);
  // dispatch 사용하기
  const dispatch = useDispatch();

  const [name, setName] = useState("홍길동");
  const [age, setAge] = useState(20);

  const handleInputName = (e) => {
    setName(e.target.value);
  };

  const handleInputAge = (e) => {
    setAge(e.target.value);
  };

  // dispatch를 통해 action을 store로 전달
  const submitName = () => {
    dispatch(changeName(name));
  };

  const submitAge = () => {
    dispatch(changeAge(age));
  };

  return (
    <div className="App" style={{ display: "flex", flexDirection: "column" }}>
      <div>{`현재 이름은 ${info.name} 입니다.`}</div>
      <div>{`현재 나이는 ${info.age}세 입니다.`}</div>
      <div>
        <label>
          이름
          <input onChange={handleInputName}></input>
          <button onClick={submitName}>이름 변경</button>
        </label>
      </div>
      <div>
        <label>
          나이
          <input type="number" onChange={handleInputAge}></input>
          <button onClick={submitAge}>나이 변경</button>
        </label>
      </div>
    </div>
  );
}

export default App;

 

4. 구현된 코드로 보기

함께 보면 좋은 글

2023.10.09 - [react/상태관리] - redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)

 

redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)

redux toolkit 없이 전역 상태 관리 하는 방법을 알아봅니다. 현재는 toolkit 사용을 권장하고 있어, 오늘날에 사용되는 코드는 아닙니다. redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레

ddmoonddmoon.tistory.com

 

 redux toolkit 없이 전역 상태 관리 하는 방법을 알아봅니다. 현재는 toolkit 사용을 권장하고 있어, 오늘날에 사용되는 코드는 아닙니다.

redux 기본 라이브러리로 전역상태 관리하기 (without toolkit, 레거시)

 

 목차

 

1. redux란?

2. redux의 구성

3. 장점

4. 단점

5. 구현

6. 구현된 코드로 보기

 

1. redux란?

  • react에서 사용되는 전역 상태 관리 라이브러리
  • 기존의 하향식 전달에서 벗어나 어디서든 상태를 참조, 변경을 가능하게끔 함

2. redux의 구성

  • state
    • redux에서 관리하는 상태 정보

 

  • action
    • 상태를 변경하는 요청
    • 어떠한 상태 변경을 하겠다를 타입에 명시
    • ex) 이름을 변경시키겠다, 나이를 변경시키겠다

 

  • reducer
    • 이전 state와 action을 받아 새로운 상태를 반환하는 함수
    • 액션에 담긴 타입에 맞춰 로직 실행
    • 상태를 변경시키는 로직이 담겨 있음

 

  • store
    • state, action, reducer 모두를 관리하는 중앙 저장소
    • action을 reducer로 전달하여 상태 변경을 적용

 

  • dispatch
    • action을 store로 전달하는 메서드
redux 작동 과정

3. 장점

  • 쉬운 디버깅
    • redux devtools를 사용하면 디버깅이 쉬움

 

  • 높은 점유율
    • redux는 다른 상태 관리 라이브러리와 비교해 점유율이 높음
    • 따라서 관련 자료들을 쉽게 찾을 수 있음

 

  • middleware 지원
    • middleware는 reducer가 action을 처리하기 전에 추가적인 로직을 가능하게 해줌
    • 비동기 작업, 인증 등 추가적인 작업을 처리가능

 

4. 단점

  • boilerplate (작성해야 하는 코드가 많음)
    • redux를 사용하기 위해 기본적으로 작성해야 하는 코드가 많은 편
    • redux-toolkit 등의 라이브러리를 통해 코드를 줄일 수 있지만, 그럼에도 다른 상태 관리 라이브러리로 보다는 코드가 긴편

 

  • 비동기 작업 복잡
    • 비동기 작업을 처리하기 위해 Redux Thunk, Redux Saga 등 middleware를 사용할 수 있지만, 이 역시 다른 상태 관리 라이브러리 보다 사용법이 다소 복잡한 편

5. 구현

  • reducer 설치

 

npm i redux react-redux redux-devtools-extension

 

  • reducer를 작성
    • 초기 상태 값을 작성
    • reducer 내부에 각 액션에 따라 어떠한 로직을 실행할 지 작성
    • action을 작성, payload는 action의 parameter를 의미
    • 생성한 reducer와 action을 export

 

// store/reducers/infoReducer.js

// 기본 상태 값을 설정
const initialState = {
  name: "홍길동",
  age: 20,
};

// reducer를 작성
// 각 액션에 따라 어떠한 로직을 실행할 지 작성
const infoReducer = (state = initialState, action) => {
  switch (action.type) {
    case "CHANGENAME":
      return { ...state, name: action.payload };
    case "CHANGEAGE":
      return { ...state, age: action.payload };
    default:
      return state;
  }
};

// 액션 작성

// changeName 액션 작성
// payload는 action에 담긴 parameter를 의미
const changeName = (value) => ({
  type: "CHANGENAME",
  payload: value,
});

// changeAge 액션 작성
const changeAge = (value) => ({
  type: "CHANGEAGE",
  payload: value,
});

// 생성한 reducer와 action export
export { infoReducer, changeName, changeAge };

 

 

  • rootReducer 작성
    •  combineReducers를 통해 생성한 reducer를 모두 묶어줌
    • comibineReducers에서 reducer에 지정한 키를 통해 상태를 불러 올 수 있음 (useSelector 부분 참고)

 

// store/reducers/rootReducer.js

import { combineReducers } from "redux";
import { infoReducer } from "./infoReducer";

// 생성한 리듀서를 하나로 묶어 줌
const rootReducer = combineReducers({

// state에서 해당 상태를 불러올 때 state.info를 통해 접근할 수 있음
  info: infoReducer,
});

export default rootReducer;

 

 

  • store 작성
    • createStore은 현재 사용을 권장하지 않음. 현재 코드에서는 redux toolkit을 사용하지 않기에 사용
    • store에 rootReducer 추가
    • composeWithDevTools()를 적용하여 redux 개발자 도구 사용 가능

 

import { createStore } from "redux";
import rootReducer from "./reducers/rootReducer";
import { composeWithDevTools } from "redux-devtools-extension";

// store를 생성
// createStore은 현재 권장되지 않는 방법, 앞으로는 toolkit의 configureStore를 사용합시다.
// store에는 rootReducer를 넣어줌
// composeWithDevTools를 넣어 redux 스토어의 변화를 확인할 수 있음
const store = createStore(rootReducer, composeWithDevTools());

export default store;

 

  • redux를 사용하고자 하는 컴포넌트 최상단에 store 적용

 

// main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store/store";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
  
    {/* redux를 이용하고자 하는 컴포넌트 최상단에 store를 적용 */}
    <Provider store={store}>
      <App />
    </Provider>
  </React.StrictMode>
);

 

  • redux 사용하기
    • useSelector로 store 상태 불러오기
    • useDispatch로 dispatch 사용하기
    • dispatch를 통해 action을 store로 전달하기

 

import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { changeAge, changeName } from "./store/reducers/infoReducer";

function App() {

  // useSelector를 통해 store의 상태를 불러올 수 있음
  // rootReducer의 할당한 키를 통해 불러올 수 있음
  const info = useSelector((state) => state.info);

  // useDispatch에 action을 이용하면 상태 변화 로직을 실행할 수 있음
  const dispatch = useDispatch();

  const [name, setName] = useState("홍길동");
  const [age, setAge] = useState(20);

  const handleInputName = (e) => {
    setName(e.target.value);
  };

  const handleInputAge = (e) => {
    setAge(e.target.value);
  };

  const submitName = () => {
  
    // action을 dispatch를 통해 store로 전달
    // changeName에 해당하는 상태 변화 로직 실행
    dispatch(changeName(name));
  };

  const submitAge = () => {
  
    // action을 dispatch를 통해 store로 전달
    // changeAge에 해당하는 상태 변화 로직 실행
    dispatch(changeAge(age));
  };

  return (
    <div className="App" style={{ display: "flex", flexDirection: "column" }}>
      <div>{`현재 이름은 ${info.name} 입니다.`}</div>
      <div>{`현재 나이는 ${info.age}세 입니다.`}</div>
      <div>
        <label>
          이름
          <input onChange={handleInputName} />
        </label>
        <button onClick={submitName}>이름 변경</button>
      </div>
      <div>
        <label>
          나이
          <input type="number" onChange={handleInputAge} />
        </label>
        <button onClick={submitAge}>나이 변경</button>
      </div>
    </div>
  );
}

export default App;

 

  • devtools 사용
    • chrome extension 에서 redux devtools 설치 
    • 현재 state와 실행 되었던 action 확인
     

redux devtools 설치

 

redux devtools 실행

 

좌측 action, 우측 state 확인

6. 구현된 코드로 보기

'react > 상태관리' 카테고리의 다른 글

redux toolkit으로 전역 상태 관리하기  (1) 2023.10.09
mobx 사용하기  (0) 2023.10.06

 custom hook은 특정 상태 관리를 재사용하기 위해 사용자 임의로 만드는 hook입니다. 동일한 상태 관리 로직을 여러 컴포넌트에서 사용해야 할 때 유용합니다.

custom hook 패턴 적용하기

 

목차

 

1. custom hook이란?

2. 특징

3. 적용법

4. 적용된 코드로 보기

 

1. custom hook이란?

  • 상태 관리, 변경 로직을 재사용하기 위한 사용자 정의 hook
  • 여러 컴포넌트에서 동일한 상태 관리 로직을 사용할 때 유용

2. 특징

  • "use"접두사 사용
    • 작성한 custom hook은 "use" 접두사를 붙여 custom hook이라는 것을 명시

 

  • 기존 react hook 결합 가능
    • useState, useEffect 등 기존 hook과 결합하여 상태 관리 가능

 

  • 재사용 용이
    • 여러 컴포넌트에서 동일한 상태 관리 로직이 필요할 때 재사용 용이
    • 전역 상태 관리와는 달리 여러 컴포넌트에서 동일한 상태를 유지할 필요가 없을 때 사용
    • 전역 상태와 동일한 상태 관리 로직을 구분하여 생각할 것

 

  • 유지 보수성 향상
    • 하나의 상태에 대한 코드들을 모두 custom hook에서 관리하므로 문제 발생시 살펴봐야할 부분을 한정시킬 수 있음

3. 적용법

  • "use" 접두사를 붙여 custom hook 파일 생성
    • useState로 관리하고자 하는 상태 생성
    • 상태 관리 함수 생성
    • 외부에서 사용하고 하는 변수 반환

 

//useCounter.jsx

import React, { useState } from "react";

const useCounter = () => {

// 관리하고자 하는 상태 생성
  const [count, setCount] = useState(0);

// 상태 관리 함수 생성
  const handlePlus = () => {
    setCount((prev) => prev + 1);
  };

  const handleMinus = () => {
    setCount((prev) => prev - 1);
  };

// 외부에서 사용하고자 하는 변수 반환
  return { count, handlePlus, handleMinus };
};

export default useCounter;

 

  • 해당 상태를 사용하고자 하는 컴포넌트에서 반환 값 할당 받아서 사용

 

import "./App.css";
import useCounter from "./customHooks/useCounter";

function App() {

// 반환 값 할당받기
  const { count, handlePlus, handleMinus } = useCounter();

  return (
    <div className="App" style={{ display: "flex" }}>
      <button onClick={handleMinus}>-</button>
      {count}
      <button onClick={handlePlus}>+</button>
    </div>
  );
}

export default App;

4. 적용된 코드로 보기

'react > 디자인 패턴' 카테고리의 다른 글

container presenter 패턴 알아보기  (0) 2023.10.07

 container presenter는 react에서 쓰이는 디자인 패턴입니다. container는 상태, 데이터 관련 로직을, presenter는 UI 구성을 담당합니다.

container presenter 패턴 알아보기

 

목차

 

1. container presenter 패턴이란?

2. 장점

3. 단점

4. 적용법

5. 구현된 코드로 보기

 

1. container presenter 패턴이란?

  • 하나의 컴포넌트를 container, presenter로 나눠서 작성
  • container는 상태 혹은 데이터 로직을 관리하는 역할
  • presenter는 화면의 레이아웃, 스타일을 담당. container로부터 넘겨 받은 데이터를 렌더링
  • 따라서 container가 presenter를 감싸는 구조

2. 장점

  • 유지보수성
    • UI 담당하는 코드와 데이터 로직 코드가 분리되어, 하나의 파일에 담겨있는 코드가 줄어들어 코드를 이해하기 쉬워짐

 

  • 테스트 용이
    • 데이터 로직 테스트와 UI 테스트를 분리해서 진행 가능

3. 단점

  • 작은 규모의 프로젝트일 경우 오히려 복잡해 질 수 있음

 

  • hooks의 등장으로 상태, 생명 주기 관리가 간편해져 도입 의도 퇴색
    • 과거 클래스형 컴포넌트에서는 상태, 생명 주기 관리를 위한 코드가 너무 길었음
    • 그러나 hook, 함수형 컴포넌트의 등장으로 코드가 많이 간결해짐
    • hook을 사용하면 container와 presenter로 나누는 것보다 간결하게 표현할 수도 있으므로 무조건적인 사용은 지양해야함
    • 즉, 상황에 맞춰 사용할 것

4. 적용법

  • 만들고자 하는 컴포넌트 폴더를 생성
  • container 컴포넌트 생성
    • 상태, 상태관리 함수 생성 후 presenter 컴포넌트로 내려 줌
/components/counter/CounterContainer.jsx

import React, { useState } from "react";
import CounterPresenter from "./CounterPresenter";

const CounterContainer = () => {
  const [count, setCount] = useState(0);

  const handlePlus = () => {
    setCount((prev) => prev + 1);
  };

  const handleMinus = () => {
    setCount((prev) => prev - 1);
  };

  return (
    <CounterPresenter
      count={count}
      handlePlus={handlePlus}
      handleMinus={handleMinus}
    ></CounterPresenter>
  );
};

export default CounterContainer;
  • presenter 컴포넌트 생성
    • container에서 받은 상태, 상태관리 함수 적용
    • UI 작성
import React from "react";

const CounterPresenter = ({ count, handlePlus, handleMinus }) => {
  return (
    <div style={{ display: "flex" }}>
      <button onClick={handleMinus}>-</button>
      {count}
      <button onClick={handlePlus}>+</button>
    </div>
  );
};

export default CounterPresenter;
  • 사용하고자 하는 곳에서 container 불러오기
import "./App.css";
import CounterContainer from "./components/counter/CounterContainer";

function App() {
  return (
    <div className="App">
      <CounterContainer></CounterContainer>
    </div>
  );
}

export default App;

5. 구현된 코드로 보기

'react > 디자인 패턴' 카테고리의 다른 글

custom hook 패턴 적용하기  (0) 2023.10.07

 react-transition-group은 리액트 라이브러리 입니다. 이 라이브러리를 통해 컴포넌트 등장, 퇴장할 때에 애니메이션을 쉽게 적용할 수 있습니다.

react-transition-group으로 컴포넌트 등장, 삭제 시 애니메이션 넣기

 

목차

 

1. react-transition-group란?

2. 사용법

3. 구현된 코드로 보기

 

1. react-transition-group란?

  • react 어플리케이션에서 애니메이션를 쉽게 사용하기 위한 라이브러리.
  • 컴포넌트가 마운트(등장), 업데이트, 언마운트(삭제)될 때 애니메이션 효과를 적용할 수 있게 해줌

2. 사용법

  • react-transition-group 라이브러리 설치
npm i react-transition-group
  • 애니메이션 만들기
//index.css

.fade-enter {     
// 컴포넌트 마운트 시 애니메이션 시작할때의 css 설정.
  transform: translateX(-300px);
}

.fade-enter-active {   
// 컴포넌트 마운트 시 애니메이션 끝났을 때의 css 설정.
  transform: translateX(0);
  transition: transform 300ms ease-in-out;
}

.fade-exit {            
// 컴포넌트 언마운트 시 애니메이션 시작할 때의 css 설정.
  transform: translateX(0);
}

.fade-exit-active {     
// 컴포넌트 언마운트 시 애니메이션 끝났을 때의 css 설정.
  transform: translateX(-300px);
  transition: transform 300ms ease-in-out;
}
  • CSSTransition 컴포넌트로 애니메이션 실행할 컴포넌트 감싸주기
import { useState } from "react";
import { CSSTransition } from "react-transition-group";    
// 라이브러리에서 불러오기.

function App() {
  const [isShow, setIsShow] = useState(false);     
  // 컴포넌트 렌더링 조건을 담당하는 state 값.

  const toggle = () => {
    setIsShow((prevState) => !prevState);
  };

  return (
    <div className="App">
      <button onClick={toggle}>{isShow ? "Hide" : "Show"}</button>     
      // 버튼을 눌러서 컴포넌트 렌더링 여부 달라짐.
      <CSSTransition 

        in={isShow}       
        // 애니메이션의 실행 기준이 되는 상태 값.

        timeout={300}     
        // 애니메이션의 실행시간.

        classNames="fade"  
        // 애니메이션의 class 명

        unmountOnExit>      
        // 애니메이션 실행된 이후 unmount 할 것인지에 대한 설정. 해당 값이 true면 fade-exit 애니메이션이 실행된 이후 컴포넌트가 사라짐.

        <div>애니메이션</div>  

      </CSSTransition>
    </div>
  );
}

export default App;

3. 구현된 코드로 보기

mobx는 react의 상태 관리 라이브러리 입니다. class 형태로 작성하여 프로퍼티, 메서드 형태로 상태를 관리 합니다.

mobx 사용하기

 

목차

 

1. mobx란?

2. 장점

3. 단점

4. 사용법

5. 구현된 코드로 보기

 

1. mobx란?

  • react 내에서 전역 상태 관리를 할 때에 사용하는 라이브러리
  • class로 만들어서 사용
  • 관리하는 상태 값은 클래스의 프로퍼티로, 상태를 변경하는 함수는 클래스의 메서드로 생성

2. 장점

  • 코드량이 적음(boilerlplate가 적음)
    • redux는 action, reducer, store 등 작성해야하는 코드가 많음
    • mobx는 class를 만들어 프로퍼티와 메서드를 생성해주면 됨

 

  • 비동기 처리 간편
    • 생성한 메서드에 async/await 키워드를 사용하면 됨

3. 단점

  • redux와 비교해 점유율이 낮은 편
    • 관련 자료를 찾을 경우 redux가 찾기가 편할 수 있으며, 레거시 코드들의 경우 redux를 사용했을 경우가 많음

 

압도적인 redux의 점유율

 

4. 사용법

  • mobx 설치
npm install --save mobx mobx-react-lite
  • store 생성
//store/counterStore.js

import { makeAutoObservable } from "mobx";

class CounterStore {
  count = 0;

  constructor() {
    makeAutoObservable(this);
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }
}

export default new CounterStore();
  • observer를 통해 상태를 감지, 변경
import { observer } from "mobx-react-lite";
import counterStore from "./store/counterStore";
import "./App.css";
import Test from "./Test";

const App = observer(() => {   // observer로 사용.
  const handleIncrease = () => {
    counterStore.increment();   // class에서 지정한 메서드로 상태 변경
  };

  const handleDecrease = () => {
    counterStore.decrement();   
  };

  return (
    <div>
      <button onClick={handleDecrease}>-</button>
      <span>{counterStore.count}</span>   // class의 프로퍼티로 상태 불러오기
      <button onClick={handleIncrease}>+</button>

      <Test></Test>
    </div>
  );
});

export default App;

(사진) 카운터로 구현한 예시

5. 구현된 코드로 보기

axiosMockAdapter로 서버로 보내는 요청을 가로채 임의의 응답으로 바꿀 수 있습니다. 서버가 아직 완성되지 않은 단계에서 테스트 용도로 사용할 수 있습니다.

axiosMockAdapter로 테스트 응답 만들기

 

목차

 

1. axiosMockAdapter란?

2. json-server와의 차이

3. 사용법

4. 구현된 코드로 보기

 

1. axiosMockAdapter란?

  • axios를 통해 수행되는 HTTP 요청을 가로채서 가짜 응답을 반환하는 라이브러리
  • 실제 서버에 요청하지 않고도 API 호출을 테스트해 볼 수 있음

2. json-server와의 차이

  • localhost가 아닌 실제 URL로 작성해도 되서 편리
    • json-server는 localhost 포트로 열기 때문에 api 요청도 해당 주소로 보내줘야 함. 테스트 이후에는 실제 서버 URL로 변경해줘야 함
    • 그러나 axiosMockAdapter는 실제 서버 URL을 입력한 뒤, 가로채기만 하면 되므로, 이후 테스트가 끝난 후에는 가로채는 부분만 삭제해주면 정상 작동

 

  • js 파일로 작성하여 좀더 유연한 조작이 가능
    • json-server는 json을 통해 작성을 하므로 클라이언트에서 보낸 값에 특정 작업을 해야 할 경우, 조작하기가 어려움
    • 그러나 axiosMockAdapter는 js 파일로 작성하므로 조작이 좀더 자유로움

3. 사용법

  • axios-mock-adapter 설치

 

npm i axios;
npm i axios-mock-adapter --save-dev

 

  • 테스트하고자 하는 코드 작성
// example.js

import axios from "axios";
import MockAdapter from "axios-mock-adapter";

const mock = new MockAdapter(axios);

mock.onGet("https://example.com/post/read").reply((config) => {    // HTTP 요청 메서드에 맞춰 줌.
  return [200, { message: "쿼리 스트링으로 1 받았습니다." }];
});

mock.onPost("https://example.com/post/post").reply((config) => {
  const data = JSON.parse(config.data);
  return [200, { message: `본문으로 ${data.data.post} 받았습니다.` }];
});

export default mock;

 

  • 해당 URL로 요청 보내는 곳에 작성한 테스트 코드 불러오기

 

import { useEffect } from "react";
import "./App.css";
import axios from "axios";
import mock from "./mock/example";

function App() {
  useEffect(() => {
    async function getData() {
      const result = await axios.get("https://example.com/post/read", {
        params: {
          post: 1,
        },
      });
      console.log("getData의 결과는", result.data);
    }

    async function postData() {
      const result = await axios.post("https://example.com/post/post", {
        data: {
          post: 1,
        },
      });
      console.log("postData의 결과는", result.data);
    }

    getData();
    postData();
  }, []);

  return <div className="App">잘 되나 테스트</div>;
}

export default App;

4. 구현된 코드로 보기

+ Recent posts