Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

코딩 작업 상세: useCodingTask

useCodingTask(task)는 작업 목록의 ITask를 받아 코딩 작업의 속성, 사용자 정보와 객체 유형 메타데이터를 제공합니다. 코딩 작업 자체를 다시 조회하지 않고, 부모가 읽어 둔 인터페이스 인스턴스를 $as(osdkCodingTask)로 사용합니다.

선행 조건

입력 작업의 실제 객체 유형은 osdkCodingTask여야 합니다. 부모 목록은 useTasks의 $includeAllBaseObjectProperties: true로 기반 속성을 읽어야 합니다.

$as는 같은 객체를 호환되는 객체 유형으로 다루는 연산입니다. 링크를 따라 다른 객체를 찾는 연산과는 구분합니다. 호환되지 않는 유형이면 실행 중 실패할 수 있으며, 이 구현에서는 fetcher의 실패가 SWR 오류로 전달됩니다.

생성자와 담당자는 부모의 사용자 정보를 재사용합니다. 정보가 없으면 undefined이며 별도의 사용자 조회를 시작하지 않습니다.

반환값

반환값의미
codingTaskosdkCodingTask, createdBy, assignedTo를 묶은 값이며 로드 전에는 undefined입니다.
isLoading처음 상세 데이터를 준비하는 상태입니다.
isValidating초기 처리나 재검증이 진행 중인 상태입니다.
isError상세 fetcher에서 발생한 오류입니다.
metadata객체 유형의 표시 이름과 속성 구성 등이며 별도로 로드합니다.

훅 구현

dataServices/useCodingTask.ts에 둡니다. 객체 인스턴스와 사용자 정보는 부모에서 얻고, 메타데이터만 클라이언트로 요청합니다.

/*
 * Copyright 2025 Palantir Technologies, Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
  * Modified example: Separate cache keys by task kind, type missing users, and handle metadata rejection.
 */

import { useCallback, useEffect, useState } from "react";
import useSWR from "swr";
import { useOsdkClient } from "@osdk/react";
import type { ITask } from "./useTasks";
import { osdkCodingTask } from "@advanced-to-do-application/sdk";
import type { User } from "@osdk/foundry.admin";
import type { ObjectMetadata } from "@osdk/client";

interface CodingTaskEnriched {
  osdkCodingTask: osdkCodingTask.OsdkInstance;
  createdBy: User | undefined;
  assignedTo: User | undefined;
}

function useCodingTask(task: ITask) {
  const client = useOsdkClient();
  const [metadata, setMetadata] = useState<ObjectMetadata>();
  const fetcher = useCallback(async (): Promise<CodingTaskEnriched> => {
    const codingTask = task.osdkTask.$as(osdkCodingTask);
    return {
      osdkCodingTask: codingTask,
      createdBy: task.createdBy,
      assignedTo: task.assignedTo,
    };
  }, [task]);

  const { data, error, isLoading, isValidating } = useSWR<CodingTaskEnriched>(
    ["codingTask", task.osdkTask.$objectType, task.osdkTask.$primaryKey],
    fetcher,
    { revalidateOnFocus: false, revalidateOnReconnect: false },
  );

  useEffect(() => {
    let active = true;
    setMetadata(undefined);
    void client.fetchMetadata(osdkCodingTask).then(value => {
      if (active) setMetadata(value);
    }).catch(console.error);
    return () => { active = false; };
  }, [client]);

  return { codingTask: data, isLoading, isValidating, isError: error, metadata };
}

export default useCodingTask;

useCallback은 입력 task가 같을 때 fetcher 참조를 유지합니다. 캐시 키에는 상세 종류, 실제 객체 유형과 기본 키를 넣어 다른 상세 유형과 구분합니다.

포커스 복귀와 네트워크 재연결에 따른 자동 재검증은 끄지만, 모든 자동 재검증이나 SWR의 오류 재시도를 끄는 설정은 아닙니다. 캐시가 있으면 fetcher가 항상 실행되지 않는다고 가정해서는 안 됩니다.

같은 기본 키의 부모 작업 내용이 바뀔 때 이 훅이 상세 캐시의 재검증을 강제하지는 않습니다. 목록과 상세가 같은 시점의 값을 표시해야 한다면 해당 codingTask 키도 무효화해야 합니다. 큰 코드 본문을 표시할 때는 화면의 렌더링 비용도 고려합니다.

상세 화면

객체 유형의 표시 이름, 언어, 코드 본문과 담당자를 표시합니다. Coding Task, Unassigned, Unknown은 메타데이터나 사용자 정보가 없을 때 쓰는 화면 문구입니다. 메타데이터는 상세 데이터보다 늦게 도착할 수 있으며, 조회 오류는 Console에 기록합니다.

import useCodingTask from '../dataServices/useCodingTask';
import type { ITask } from '../dataServices/useTasks';

function CodingTaskDetails({ task }: { task: ITask }) {
  const { codingTask, isLoading, isError, metadata } = useCodingTask(task);
  
  if (isLoading) return <div>Loading coding task details...</div>;
  if (isError) return <div>Error loading coding task: {isError.message}</div>;
  if (!codingTask) return <div>No coding task found</div>;
  
  return (
    <div className="coding-task-details">
      <h2>{codingTask.osdkCodingTask.title}</h2>
      
      <div className="metadata-section">
        <h3>Task Metadata</h3>
        <div>Object Type: {metadata?.displayName || "Coding Task"}</div>
      </div>
      
      <div className="code-section">
        <h3>Code Requirements</h3>
        <div className="language-badge">{codingTask.osdkCodingTask.language}</div>
        <pre>
          <code>{codingTask.osdkCodingTask.codeSnippet}</code>
        </pre>
      </div>
      
      <div className="people-section">
        <h3>People</h3>
        <div className="assigned-to">
          <span>Assigned to: </span>
          <span>{codingTask.assignedTo?.username ?? "Unassigned"}</span>
        </div>
        <div className="created-by">
          <span>Created by: </span>
          <span>{codingTask.createdBy?.username ?? "Unknown"}</span>
        </div>
      </div>
    </div>
  );
}

이 훅은 조회와 화면 표시를 담당합니다. 작업 생성, 수정과 삭제는 액션 호출 등 별도의 변경 경로에서 수행해야 합니다.