1. 리액트 18의 새로운 기능 활용

(1) Concurrent 렌더링 이해와 활용

[번역] 리액트 동시성 이해하기

useTransition – React

핵심 개념

Concurrent 렌더링은 React 18에서 도입된 핵심 기능으로, 렌더링 작업을 중단, 재개, 우선순위 지정할 수 있게 해줍니다. 이를 통해 사용자 인터페이스의 반응성을 크게 향상시킬 수 있습니다.

주요 특징:

Concurrent 렌더링을 활용한 검색 기능 구현

AS-IS

import React, { useState, useEffect } from 'react';

function SearchComponent({ searchTerm }) {
  const [results, setResults] = useState([]);

  useEffect(() => {
    const fetchResults = async () => {
      const response = await fetch(`/api/search?q=${searchTerm}`);
      const data = await response.json();
      setResults(data);
    };

    fetchResults();
  }, [searchTerm]);

  return (
    <ul>
      {results.map(item => (
        <li key={item.id}>{item.title}</li>
      ))}
    </ul>
  );
}

TO-BE

import React, { useState, useTransition } from 'react';

function SearchComponent({ searchTerm }) {
  const [results, setResults] = useState([]);
  const [pending, startTransition] = useTransition();

  useEffect(() => {
    startTransition(async () => {
      const response = await fetch(`/api/search?q=${searchTerm}`);
      const data = await response.json();
      setResults(data);
    });
  }, [searchTerm]);

  return (
    <>
      {pending && <p>Searching...</p>}
      <ul>
        {results.map(item => (
          <li key={item.id}>{item.title}</li>
        ))}
      </ul>
    </>
  );
}

useTransition을 이용한 탭 전환 최적화

AS-IS (React 17)

import React, { useState } from 'react';

function TabComponent() {
  const [activeTab, setActiveTab] = useState('home');

  const renderTabContent = () => {
    switch (activeTab) {
      case 'home':
        return <HomeContent />;
      case 'profile':
        return <ProfileContent />;
      case 'settings':
        return <SettingsContent />;
      default:
        return null;
    }
  };

  return (
    <div>
      <div>
        <button onClick={() => setActiveTab('home')}>Home</button>
        <button onClick={() => setActiveTab('profile')}>Profile</button>
        <button onClick={() => setActiveTab('settings')}>Settings</button>
      </div>
      {renderTabContent()}
    </div>
  );
}

function HomeContent() {
  // 복잡한 렌더링 로직
  return <div>Home Content</div>;
}

function ProfileContent() {
  // 복잡한 렌더링 로직
  return <div>Profile Content</div>;
}

function SettingsContent() {
  // 복잡한 렌더링 로직
  return <div>Settings Content</div>;
}

TO-BE (React 18 with Concurrent Features)

import React, { useState, useTransition } from 'react';

function TabComponent() {
  const [activeTab, setActiveTab] = useState('home');
  const [isPending, startTransition] = useTransition();

  const handleTabChange = (tab) => {
    startTransition(() => {
      setActiveTab(tab);
    });
  };

  const renderTabContent = () => {
    switch (activeTab) {
      case 'home':
        return <HomeContent />;
      case 'profile':
        return <ProfileContent />;
      case 'settings':
        return <SettingsContent />;
      default:
        return null;
    }
  };

  return (
    <div>
      <div>
        <button onClick={() => handleTabChange('home')}>Home</button>
        <button onClick={() => handleTabChange('profile')}>Profile</button>
        <button onClick={() => handleTabChange('settings')}>Settings</button>
      </div>
      {isPending ? <div>Loading...</div> : renderTabContent()}
    </div>
  );
}

// HomeContent, ProfileContent, SettingsContent 컴포넌트는 이전과 동일