FrontEnd/React

리액트 18 버전 정리

Automatic Batching

기존 방식

Automatic Batching 적용

 

// 기존 버전
setTimeout(() => {
    setCount((count) => count + 1);
    setIsFull((isFull) => !isFull);
    // 각 state의 업데이트 마다 재렌더링이 발생
}, 1000)

// 현재 버전
setTimeout(() => {
    setCount((count) => count + 1);
    setIsFull((isFull) => !isFull);
    // 재렌더링이 마지막에 한 번만 발생 (Automatic Batching)
}, 1000);

Transitions

긴급한 업데이트와 긴급하지 않은 업데이트를 구분해서 처리하기 위한 개념

 

업데이트의 종류

  • 긴급한 업데이트
    • 사용자와 직접적인 인터랙션이 일어나는 경우
    • 예) 글자 입력, 버튼 클릭 등
  • 긴급하지 않은 업데이트
    • 사용자와 직접적인 인터랙션이 일어나지 않는 경우
    • 예) 서버로부터 결과를 받아와서 보여주는 경우
import { startTransition } from "react";

// 긴급 업데이트: 입력한 글자를 화면에 보여주어야 함
setInputValue(input);

// 함수 내에 있는 모든 업데이트는 Transition 업데이트가 됨
startTransition(() => {
    // Transition 업데이트: 검색 결과를 보여주어야 함
    setSearchQuery(input);
});

Suspense

하위 컴포넌트(children)준비되기 전까지 렌더링을 중단하는 것

 

웹사이트 규모 ↑ / 컴포넌트 사이즈 ↑ / 로딩 시간 ↑

 

Code Splitting

Lazy Loading / Dynamic Loading

 

import { lazy, Suspense } from "react";
import LoadingSpinner from './LoadingSpinner';
const OtherComponent = lazy(() => import('./OtherComponent'));

function MyComponent(props) {
    return (
        <Suspense fallback={LoadingSpinner />}>
            <OtherComponent />
        </Suspense>
    );
}

export default MyComponent;
// OtherComponent가 준비되기 전까지 
// fallback 속성에 들어가있는 LoadingSpinner라는 컴포넌트를 화면에 보여주고
// OtherComponent가 준비되면 그때 OtherComponent를 보여줌

클라이언트와 서버 렌더링 API 업데이트

리액트 DOM 클라이언트 변경사항

 

기존방식 (리액트 버전17)

import React from "react";
import ReactDOM from 'react-dom';
import App from './App';

ReactDOM.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>,
    document.getElementById('root')
);

 

새로운 방식 (리액트 버전 18)

import React from "react"
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
    <React.StrictMode>
        <App />
    </React.StrictMode>
);

 

리액트 DOM 서버

  • renderToPipeableStream
    • NodeJS 환경에서 스트리밍을 위한 함수
  • renderToReadableStream
    • Edge runtime 환경(예: Deno, Cloudflare workers)을 위한 함수

새로운 Strict 모드 작동 방식

Strict Mode

언마운트(unmount) 시켰다가 다시 한 번 마운트(mount) 시킴

컴포넌트 생명주기 함수들이 예상과 다르게 여러번 호출 될 수 있음


새롭게 추가된 훅들

useId()

서버와 클라이언트에서 고유한 id값을 생성하기 위한 hook

list rendering시 map함수 내에서 반환하는 element key사용 용도는 아님

import { useId } from 'react';

function MyComponent() {
  const id = useId();

  return (
    <div>
      <label htmlFor={id}>이름:</label>
      <input id={id} type="text" />
    </div>
  );
}

 

useTransitions()

긴급하지 않은 update를 위한 hook

import { useState, useTransition } from 'react';

function MyComponent() {
  const [isPending, startTransition] = useTransition();
  const [count, setCount] = useState(0);

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

  return (
    <div>
      <button onClick={handleClick}>카운트 증가</button>
      {isPending ? <p>업데이트 중...</p> : <p>카운트: {count}</p>}
    </div>
  );
}

 

useDeferredValue()

긴급하지 않은 update를 재렌더링 하는것을 연기할 수 있게 해주는 hook

짧은 시간에 한 가지 상태의 update가 여러번 발생 했을 경우 최종 상태값만 update하면 됨 (debouncing) 

지연된 렌더링은 중단 가능하며 사용자의 입력을 차단하지 않음

import { useState, useDeferredValue } from 'react';

function MyComponent() {
  const [text, setText] = useState('');
  const deferredText = useDeferredValue(text);

  const handleChange = (e) => {
    setText(e.target.value);
  };

  return (
    <div>
      <input type="text" value={text} onChange={handleChange} />
      <p>입력한 텍스트: {deferredText}</p>
    </div>
  );
}

 

useSyncExternalStore()

외부 저장소를 구독 할 수 있게 해주는 hook

import { useSyncExternalStore } from 'react';

function useMyStore(selector) {
  return useSyncExternalStore(
    myStore.subscribe,
    () => selector(myStore.getState()),
    () => selector(myStore.getSnapshot())
  );
}

 

useInsertionEffect()

CSS-in-JS 라이브러리를 위한 hook 

렌더링 과정에서 스타일 삽입의 성능 문제를 해결 할 수 있게 해줌

import { useInsertionEffect } from 'react';

function MyComponent() {
  useInsertionEffect(() => {
    const style = document.createElement('style');
    style.textContent = `
      .my-class {
        color: red;
      }
    `;
    document.head.appendChild(style);
    return () => {
      document.head.removeChild(style);
    };
  }, []);

  return <div className="my-class">안녕하세요, 세계!</div>;
}

'FrontEnd > React' 카테고리의 다른 글

연차 관리 캘린더 프로젝트 With ChatGpt #1  (0) 2024.06.13
연차 관리 캘린더 프로젝트 With ChatGpt #0  (1) 2024.06.04
Mini Project  (0) 2024.05.21
Styling  (0) 2024.05.08
Context  (0) 2024.04.30