본문 바로가기

자바스크립트

리액트 19가 또 나오네

2024년 연말에 리액트 19가 나올 예정이다.

 

블로그

 

useMemo, useCallback, memo는 리액트에서 불필요한 리렌더링 최적화를 진행하는데 없어서는 안될 훅이다.

그런데 이번 19버전에서는 이 훅들이 사라질 예정이라고 한다. (정확히는 deprecated)

이제 리액트에서 이부분을 알아서 최적화해주는 것으로 바뀐다고 한다.

때문에 리액트 사용자들은 해당 훅들을 사용하여 최적화하는 시간에 다른 생산적인(비즈니스 로직 등)에 집중할 수있다.

 

두번째로 forwardRef가 없어진다고 한다.

const ChildComponent = React.forwardRef(
  ({ data,ref }: dataTypes, ref) => {
    return (
      <div>
      	// ...
      </div>
    );
  }
);

기존 forwardRef로 컴포넌트를 감싸 부모 컴포넌트가 자식 컴포넌트에 접근하기 위해 사용했었던 방식을 다음과 같이 수정한다고 한다.

 

const ChildComponent = ({ ref }:{ref: React.RefObject<HTMLDivElement | null>}) => {
  return (
    <div>
    </div>
  );
};

아마 타입은 이전에 사용했던 React.RefObject<Html...Element>와 같다고 예상한다.

매우 편해졌다.

 

세번째로 React.lazy가 RSC(리액트 서버 컴포넌트)로 대체가 될 것이다.

React.lazy는 현재 회사 프로젝트에서도 사용하고 있는데, 쉽게 말하면 대규모 단일 JS번들이 사용자에게 전송되는 것을 방지한다.

이제 React.lazy로 RSC로 대체되는 모습이다.

 

네번째로 use이다.

맨 위 사진에 나와있는 것은 props drilling을 피하기 위해 사용된 useContext가 "use"라는 훅으로 대체되는 모습이다. 밑에서 사용법을 간단히 보겠다.

블로그, 원문


use훅은 리액트 19버전에 도입 될 새로운 훅입니다.

컨텍스트프로미스작업에 매우 유용합니다.

use훅과 다른 훅들의 차이점은 루프또는 if와 같은 조건문 내에서 호출을 할 수 있다는 점입니다. 그러나 함수 컴포넌트나 커스텀 훅에서만 사용할 수 있다는 기본 컨셉은 다른 훅과 동일합니다.

 

서버 컴포넌트에서 데이터를 가져와 클라이언트 컴포넌트에 전달할 수 있는 RSC가 등장했습니다. 여기서 use훅이 중요한 역할을 합니다. use훅을 사용하면 프로미스와 컨텍스트에서 값을 가져올 수 있습니다.

 

use훅을 사용하여 프로미스 처리하기

// 서버 컴포넌트

import { fetchMessage } from './lib.js';
import { Message } from './message.js';

const App = () => {
  const messagePromise = fetchMessage();
  return <Message messagePromise={messagePromise} />;
};

export default App;

위 코드에서 볼 수 있듯이 서버 컴포넌트에서 메세지 데이터를 가져와 클라이언트 컴포넌트로 전달하고 있습니다. 이제 클라이언트 컴포넌트에서 use훅을 사용하여 이 프로미스를 사용할 수 있습니다.

// 클라이언트 컴포넌트(message.js)

'use client';

import { use } from 'react';

export function Message({ messagePromise }) {
  const messageContent = use(messagePromise);
  return <p>Here is the message: {messageContent}</p>;
}

 

에러처리 또한 suspense와 error boundary로 처리할 수 있습니다.

import { use, Suspense } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { fetchMessage } from './lib.js';
import { Message } from './message.js';

const App = () => {
  const messagePromise = fetchMessage();

  return;
  <ErrorBoundary fallback={<p>⚠️Something went wrong</p>}>
    <Suspense fallback={<p>Loading...</p>}>
      <Message messagePromise={messagePromise} />
    </Suspense>
  </ErrorBoundary>;
};

export default App;

 

또한 이제 use 훅의 도움으로 클라이언트 컴포넌트에서 컨텍스트 값을 사용할 수 있습니다.

// 컨텍스트 컴포넌트

'use client';

import { createContext, useState } from 'react';

export const AppContext = createContext();

export const AppContextProvider = ({ children }) => {
  const [state, setState] = useState('Hello from context!');

  return (
    <AppContext.Provider value={{ state, setState }}>
      {children}
    </AppContext.Provider>
  );
};

간단히 컨텍스트를 생성하고 컨텍스트에 값을 제공했습니다. 이제 클라이언트 컴포넌트에서 use 훅을 사용하여 이 컨텍스트 값을 사용할 수 있습니다.

'use client';

import { AppContext } from '@/contexts/app-context';
import { use } from 'react';

const ContextExample = () => {
  const { state, setState } = use(AppContext);

  return (
    <div>
      <h1>{state}</h1>
      <button onClick={() => setState('Hello from context component!')}>
        Change
      </button>
    </div>
  );
};
export default ContextExample;

 

조건문 또한 간단합니다.

 

'use client';

import { AppContext } from '@/contexts/app-context';
import { use } from 'react';

const ContextExample = () => {
  const [active, setActive] = useState(false);
  const { state, setState } = use(AppContext);

  if (active) {
    return (
      <div>
        <h1>{state}</h1>
        <button onClick={() => setState('Hello from context component!')}>
          Change
        </button>
      </div>
    );
  }

  return (
    <div>
      <h1>Click the button to activate the context</h1>
      <button onClick={() => setActive(true)}>Activate</button>
    </div>
  );
};

export default ContextExample;

상당히 많은 모습이 보인다.

useContext를 사용할 때 useContext(AppCtx)로 state를 선언하는 것이 아닌 use훅의 도움으로 간단하게 context값을 선언할 수 있게되었다. 또한 use훅의 도움으로 서버 컴포넌트에서 받아온 데이터를 손쉽게 클라이언트 컴포넌트에 렌더링할 수 있다.

 

 

마지막으로 <Content.Provider>가 <Context>로 바뀐다.

코드가 좀 더 간결해지는 느낌이다.

 

대체적으로 많은 부분이 바뀌었다면 바뀐건데, 리액트 서버컴포넌트의 등장만큼의 대격변은 없는 듯하다. 새로운 기술을 개발하는 것 대신 기존에 존재하던 기술들을 좀 더 손쉽게 사용하도록 바뀐, 리팩토링 부분에 초점이 맞춰진듯하다.