지속적인 오류 파티이다.
npm에서 react-infinite-scroller를 다운받아 무한 스크롤을 구현하는 과정에서
return문안에서 컴퍼넌트로 적용하는 연습을 했다. 모듈을 설치하고 컴퍼넌트로 삽입하라고
한 InfiniteScroller를 return문안에서 적용하니 유효한 jsx 요소로서 사용할수 없다고 한다.
설명에는 분명 return문안에 component로 끼워넣어져야 한다고 되어 있는데..흠흠..
타입관련 오류가 나타나고 화면 렌더링에도 문제가 있었다.
IDE에 나타나는 타입 관련 오류는 아래와 같은데, 'ref'속성이 없어서 JSX 컴퍼넌트로서 적용해 쓸수 없다는 의미이다. 'ref'는 React.component에서 상속되어 제공된다고 한다.
오류내용 : 'InfiniteScroll' cannot be used as a JSX component.Its instance type 'InfiniteScroll' is not a valid JSX element.
Property 'refs' is missing in type 'InfiniteScroll' but required in type 'ElementClass'.ts(2786)index.d.ts(507, 9): 'refs' is declared here.
( Typescript는 형식을 엄청 따지는 고지식한 친구인지라 .. 타입체크를 위한 도구인 ElementClass type.ts가지고 체크해 보니깐 꼭 필요한 'ref'가 없는데? 아, 넌.. 이상한 코드구나. 입장불가~ 이러면서 되돌려보냈다는 것이다. )
콘솔에 나타나는 렌더링 오류는 더욱 길고 복잡하지만 typescript가 내보내는 오류와는 상관이 없어보였다. 해당 모듈의 typescript 적용 전 구 버전의 코드는 아래와 같이 Component를 Extend한 클래스형 컴퍼넌트이므로 타입이 맞지 않더라도 화면 렌더링은 되어야 할것 같은데 .. Next의 특성상 SSR로 구동되면서 충돌이 생긴 듯하여 CSR로 구동되도록 변경해줄 필요가 있었다.
import React, { Component } from 'react';
class InfiniteScroll extends Component {
render() {
return <div>Infinite Scroll</div>;
}
}
export default InfiniteScroll;
렌더링 부분해결
1) next/dynamic 사용
Next는 SSR중에는 브라우저 관련 객체(window, document)를 사용할수 없다. 따라서, 서버에서 컴포넌트를 렌더링할때 react-infinite-scroller처럼 props에서 window등의 브라우저 API를 사용하면 오류가 발생할수 있다. 이러한 상황에 대해 dynamic모듈을 이용해 모듈을 받아오면서 ssr을 false로 설정해 클라이언트에서 화면이 렌더링 되도록 설정했다.
import dynamic from "next/dynamic";
const InfiniteScroll = dynamic(() => import("react-infinite-scroller"), {
ssr: false,
});
적용해 보니 화면 렌더링은 정상적으로 표현되었다. 다만, 함수상에 Typescript에서 기인하는 타입 오류들이 나타난다.(Argument of type '() => Promise<{ default: typeof InfiniteScroll.InfiniteScroll; prototype: InfiniteScroll.InfiniteScroll; contextType?: React.Context<any> | undefined; propTypes?: any; }>' is not assignable to parameter of type 'DynamicOptions<InfiniteScrollProps> | Loader<InfiniteScrollProps>'.... 등)
더불어, 하단에 return문안에서도 해당 컴퍼넌트를 적용하는 <InfiniteScroll />부분에서도 JSX로 표시될수 없다는 오류가 여전히
나타난다.
TypeScript 오류의 회피나 우회
Chat GPT가 속~ 편하게 여러가지 방법을 제시해 줬다.
1) Typescript를 무시하고 진행해봐 ( ts-ignore에 넣으면 될거라고 한다. 읏.. 이건 아니니깐 안해봤다)
2) 해당 모듈을 typescript를 피해서 require로 가져와봐( CJS와 ESM의 충돌사고를 피해보란 얘기같다, Next에서는 시도해보고 싶지않다. )
3) type을 React.Component로 캐스트 (unknown을 사용해서 우회하는 것이 보다 안전하다고 한다)
const TypedInfiniteScroll = InfiniteScroll as unknown as React.ComponentType<any>;
<TypedInfiniteScroll />
TypeScript 오류와 렌더링 오류를 동시에 사라지게 ~
1) dynamic과 type cast를 함께 적용
- dynamic을 통해 렌더링의 오류가 사라진다. 타입에 대한 오류 문구가 사라지고 렌더링도 잘 된다. 다만, ComponentType을 any로 두어 타입스트립트의 타입 제어가 안되는 좀 아쉬운 상황이다.
import dynamic from "next/dynamic";
const InfiniteScroll = dynamic(
() =>
import("react-infinite-scroller").then(
(mod) => mod.default as unknown as ComponentType<any>,
),
{ ssr: false },
);
2) InfiniteScroll의 props type을 직접 규정해주어 타입스크립트로 오류제어 가능하도록 변경
- InfiniteScrollProps로 타입형태를 필요한 부분만 정의해서 타입오류를 없애고, dynamic을 이용하여 csr로만 구동되게 정의한다. ( InfiniteScrollProps를 보면 useWindow라는 부분이 있다. 아마도, 저 부분때문에 csr로 구동되어야 하는것 같다. )
interface InfiniteScrollProps {
pageStart?: number;
loadMore: (page: number) => void;
hasMore: boolean;
loader?: React.ReactNode | null;
useWindow?: boolean;
children?: React.ReactNode;
}
const InfiniteScroll = dynamic(
() =>
import("react-infinite-scroller").then(
(mod) =>
mod.default as unknown as React.ComponentType<InfiniteScrollProps>,
),
{ ssr: false },
);
3) 모듈 자체를 직접 선언하여 csr문제와 타입 문제를 한꺼번에 처리
- 내부에 props의 타입을 규정해 주어 타입 컨트롤 기능을 살리고, InfiniteScroll을 함수로서 export해줌으로서 클라이언트에서 렌더링 되도록 구성해준다. ( 해당 컴퍼넌트 내부에서 처리했으나 global.d.ts에서 내보내주는 게 보다 자연스럽겠다.)
import InfiniteScroll from "react-infinite-scroller";
declare module "react-infinite-scroller" {
interface InfiniteScrollProps {
pageStart?: number;
loadMore: (page: number) => void;
hasMore: boolean;
loader?: React.ReactNode | null;
useWindow?: boolean;
children?: React.ReactNode;
}
export default function InfiniteScroll(
props: InfiniteScrollProps,
): ReactElement;
}
'growth-log' 카테고리의 다른 글
Recoil_ React상태 관리 (0) | 2025.03.08 |
---|---|
반도체의 유리기판 ? (0) | 2025.02.15 |
CJS와 ESM (0) | 2025.01.22 |
방송통신대 CS 마지막 학기의 후기 (2) | 2024.12.16 |
Youtube 데이터 크롤링 (3) | 2024.10.12 |