24.11.25

강연주·2024년 11월 25일

📚 TIL

목록 보기
102/186

타입스크립트에서 ref 사용하는 중 🫠

🖥️ interface Meetup {
  name: string;
  description: string;
  place: string;
  placeDescription: string;
  startedAt: string | null;
  endedAt: string | null;
  adTitle: string;🔥
  adEndedAt: string | null;
  isPublic: boolean;
  image: string;
  category: string;
}

...

  const nameRef = useRef<HTMLInputElement>();
  const startedAtRef = useRef<HTMLInputElement>();
  const endedAtRef = useRef<HTMLInputElement>();
  const placeRef = useRef<HTMLInputElement>();
  const placeDescriptionRef = useRef<HTMLInputElement>();
  const adTitleRef = useRef<HTMLInputElement>();🔥
  const adEndedAtRef = useRef<HTMLInputElement>();
  const descriptionRef = useRef<HTMLInputElement>();
  const isPublicRef = useRef<HTMLInputElement>();
  const categoryRef = useRef<HTMLInputElement>();
  const imageRef = useRef<HTMLInputElement>();
  
  const placeDescription = placeDescriptionRef.current?.value || "";
    console.log("Submitted placeDescription:", placeDescription);

    if (!adTitleRef.current) {
      console.error("adTitleRef가 인풋에 연걸 안돼있어");
      return;
    }
    const adTitle = placeRef.current?.value || "";🔥
    console.log("Submitted adTitle:", adTitle);

    if (!adEndedAtRef) {
      console.error("adEndedAtRef가 인풋에 연결 안돼있어");
      return;
    }
    const adEndedAt = adEndedAtRef.current?.value || "";
    console.log("Submitted adEndedAt:", adEndedAt);

    if (!descriptionRef) {
      console.error("descriptionRef가 인풋에 연결 안돼있어");
      return;
    }

    // const description = descriptionRef.current.value || "";

    // const form = event.currentTarget as HTMLFormElement;
    // const isPublicValue = (form.elements.namedItem("isPublic") as HTMLInputElement).checked;

    const newMeetup: Meetup = {
      name: nameRef,🔥
      description: descriptionRef,
      place: placeRef,
      placeDescription: placeDescriptionRef,
      startedAt: startedAtRef,
      endedAt: endedAtRef,
      adTitle: adTitleRef,
      adEndedAt: adEndedAtRef,
      isPublic: isPublicRef,
      image: imageRef,
      category: categoryRef,
    };

    createMutation.mutate(newMeetup);
  };

🕹️ 오류 1

모임 제출 시 들어가는 인풋들을 인터페이스로 지정, 각각 인풋값을 ref로 관리,
TanstackQuery의 createMutation.mutate(newMeetup)을 통해
새 모임을 생성하는데, newMeetup에 아래와 같은 오류가 발생한다.

'{ name: React.MutableRefObject<HTMLInputElement | undefined>; description: React.MutableRefObject<HTMLInputElement | undefined>; ... 8 more ...; category: React.MutableRefObject<...>; }' 형식의 인수는 'Meetup' 형식의 매개 변수에 할당될 수 없습니다. 'name' 속성의 형식이 호환되지 않습니다. 'MutableRefObject<HTMLInputElement | undefined>' 형식은 'string' 형식에 할당할 수 없습니다.ts(2345)

  1. newMeetup 선언 시에 Meetup 인터페이스를 지정해주면 빨간줄이 newMeetup 안에 새로 생긴다.
  2. 그리고 name: nameRef라고 써놨는데 정작 nameRef는 선언된 적이 없다.
  3. 추측건대, ref는 사용자 입력값을 받아 동적으로 할당될 텐ep(MutableRefObject❓) Meetup 인터페이스에서는 string을 기대해서?

➡️ 문제의 원인은 createMeetup 함수에 전달된 newMeetup 객체가,
Meetup 타입을 따르지 않기 때문이다.
newMeetup에 할당된 값들은 useRef로 생성된 MutableRefObject다.
그러나 Meetup 인터페이스에서는 해당 필드들이 string 타입을 기대한다.
useRef로 생성된 객체는 current 속성을 통해 값을 참조해야 합니다.

  1. 근데 콘솔에는 문제 없이 인풋의 값들이 제출되고 있다.
  2. 아래 코드를 지워도 아무 문제가 없다. (❓왜지?)
    const description = descriptionRef.current.value || "";

0-1. newMeetup 선언 시에 Meetup 인터페이스를 지정해주면
newMeetup 안의 프로퍼티 키에 빨간줄이 생긴다.
'MutableRefObject<HTMLInputElement | undefined>' 형식은 'string' 형식에 할당할 수 없습니다.ts(2322) MeetupForm.tsx(8, 3): 필요한 형식은 여기에서 'Meetup' 형식에 선언된 'description' 속성에서 가져옵니다.

🖥️ const newMeetup: Meetup = {
      name: nameRef.current?.value || "", // name: nameRef였음 ㅜㅜ
      description: descriptionRef.current?.value || "",
      place: placeRef.current?.value || "",
      placeDescription: placeDescriptionRef.current?.value || "",
      startedAt: startedAtRef.current?.value || "",
      endedAt: endedAtRef.current?.value || "",
      adTitle: adTitleRef.current?.value || "",
      adEndedAt: adEndedAtRef.current?.value || "",
      isPublic: isPublicRef.current?.value || "",
      image: imageRef.current?.value || "",
      category: categoryRef.current?.value || "",
    };

그래서 nameRef.current?.value || "",처럼 모든 프로퍼티값을 변경하니
빨간줄이 귀신같이 하나 둘 지워지는 짜릿함.

  • ref.current?.value 사용
    : useRef로 생성된 ref는 current 속성을 통해 DOM 요소에 접근할 수 있다.
    각 current.value를 읽어 string 또는 null로 변환한다.

  • Meetup 타입에 맞게 변환
    : name, description, place, 등은 반드시 string이어야 하므로 ref.current?.value || ""로 기본값을 설정한다.
    startedAt과 endedAt은 null을 허용하므로
    ref.current?.value || null을 사용한다.

➡️ 이따가 isPublic 타입 문제 해결해야 한다.


🕹️ 오류 2

근데 이제 리턴부 <LabeledInput ref=""/>에서 ref에 오류가 나지.
수정하면서 난 건 아니고, 처음부터 존재했었다. 왜 동작도 하면서 빨간줄도 줘?

'MutableRefObject<HTMLInputElement | undefined>' 형식은 'LegacyRef<HTMLInputElement> | undefined' 형식에 할당할 수 없습니다. 'MutableRefObject<HTMLInputElement | undefined>' 형식은 'RefObject<HTMLInputElement>' 형식에 할당할 수 없습니다. 'current' 속성의 형식이 호환되지 않습니다. 'HTMLInputElement | undefined' 형식은 'HTMLInputElement | null' 형식에 할당할 수 없습니다. 'undefined' 형식은 'HTMLInputElement | null' 형식에 할당할 수 없습니다.ts(2322) index.d.ts(303, 9): 필요한 형식은 여기에서 'IntrinsicAttributes & LabeledInputProps & RefAttributes<HTMLInputElement>' 형식에 선언된 'ref' 속성에서 가져옵니다. (property) RefAttributes<HTMLInputElement>.ref?: React.LegacyRef<HTMLInputElement> | undefined Allows getting a ref to the component instance. Once the component unmounts, React will set ref.current to null (or call the ref with null if you passed a callback ref).

아 피곤해

profile
아무튼, 개발자

0개의 댓글