API
퓨처 API
API 변경사항

API 변경사항

Stackflow React Future

  • 새 API는 @stackflow/react/future 로 접근할 수 있어요.

다음과 같이 사용하세요.

Stack.tsx
import { stackflow } from "@stackflow/react/future";
import HomeActivity from "../components/HomeActivity";
import MyProfileActivity from "../components/MyProfileActivity";
 
// 만들어준 config를 인자로 받습니다
import { config } from "./stackflow.config";
 
export const { Stack } = stackflow({
  config,
  
  // Config에서 선언한 이름으로 리액트 컴포넌트를 주입해요
  components: {
    HomeActivity,
    MyProfileActivity,
  },
 
  // 이제 History Sync Plugin에 routes를 따로 선언할 필요가 없어요
  // 아래와 같이 플러그인을 추가하면, stackflow.config.ts에 빨간줄이 생겨요
  plugins: [
    historySyncPlugin({
      config,
      fallbackActivity: () => "FeedActivity",
    }),
  ],
});
stackflow.config.ts
import { defineConfig } from "@stackflow/config";
 
export const config = defineConfig({
  activities: [
    {
      name: "HomeActivity",
      
      // History Sync Plugin에서 요구하는 설정값을 stackflow.config에 같이 선언할 수 있어요
      path: "/",
    },
    {
      name: "MyProfileActivity",
      path: "/my-profile",
    }
  ],
  transitionDuration: 270,
});

"왜 React 컴포넌트는 Config에 같이 선언하지 않나요?"

Stackflow Config는 프레임워크 의존성이 없는 정적 정보를 담는 그릇이 되는 것이 설계의 핵심이에요. Stackflow Config는 React 의존성이 없어야 하기 때문에, 이 부분을 분리해서 React 의존성(컴포넌트)은 @stackflow/react 를 설정하는 부분에 추가하는 식으로 설계되었어요.

타입 안정성

기존에는 타입을 React 컴포넌트의 Props 타입을 통해 추론했어요. 이제 Config에서 추론하도록 변경돼요.

Config에 액티비티 파라미터 타입을 추가하려면 아래와 같이 선언해요.

declare module "@stackflow/config" {
  interface Register {
    HomeActivity: {
      regionId: string;
      referrer?: string;
    }
  }
}

전역에 해당 액티비티의 타입이 등록되고, 아래와 같이 유틸 타입을 사용할 수 있어요.

HomeActivity.tsx
import type { ActivityComponentType } from "@stackflow/react/future";
 
const HomeActivity: ActivityComponentType<"HomeActivity"> = ({ params }) => {
  params.regionId // string
  
  return (
    <div>...</div>
  )
}

또한 해당 선언은 한 장소에 모아두어도 되고, 액티비티 파일 마다 분리해도 되므로(Co-location) 원하시는대로 관리가 가능해요.

HomeActivity.tsx
declare module "@stackflow/config" {
  interface Register {
    HomeActivity: {
      regionId: string;
      referrer?: string;
    }
  }
}
MyProfileActivity.tsx
declare module "@stackflow/config" {
  interface Register {
    MyProfileActivity: {
      userId: string;
    }
  }
}

useFlow(), useStepFlow()

이제 flow() 등의 함수로 useFlow(), useStepFlow() 등의 훅을 생성할 필요가 없어요. 바로 import해서 쓸 수 있어요.

HomeActivity.tsx
import { useFlow, useStepFlow } from "@stackflow/react/future";
 
const { push } = useFlow();
const { pushStep } = useStepFlow<"HomeActivity">()
 
push("...", { ... }) // Typed
pushStep({ ... })    // Typed

타입 안정성이 자연스럽게 보장돼요.

파괴적 변환

useStepFlow()의 함수 이름이 바뀌었어요.

  • 기존: stepPush(), stepReplace(), stepPop()
  • 변경: pushStep(), replaceStep(), popStep()
  • 함수 이름이 동사로 시작하도록 명세를 수정되었어요.

<Link />

마찬가지로 createLinkComponent() 등의 함수로 <Link /> 컴포넌트를 생성할 필요가 없어요. 바로 import 해서 쓸 수 있어요. 또한 기존에 존재하던 Preload 동작을 삭제했어요.

MyComponent.tsx
import { Link } from "@stackflow/link/future";
 
function MyComponent() {
  return (
    <div>
      {/* ... */}
      <Link activityName="..." activityParams={{ /* ... */ }} />
    </div>
  )
}
💡

뷰 포트에 <Link /> 컴포넌트가 드러났을때 API 프리로딩을 하는 동작은 성능 향상에 큰 이점이 있지만 서버 부하를 크게 늘리기 때문에 잘 사용되지 않는 것으로 파악되었어요. 따라서 기본값으로 있던 기존의 프리로딩 동작을 없애고 추후 <Link /> 컴포넌트의 props를 통해 프리로딩 정책을 개발자가 세밀하게 제어할 수 있도록 추후 추가 할 예정이에요.