programing

유형 스크립트와 기본적으로 대응하는 플랫폼별 가져오기 구성 요소

testmans 2023. 7. 4. 21:46
반응형

유형 스크립트와 기본적으로 대응하는 플랫폼별 가져오기 구성 요소

나는 타입스크립트와 함께 리액트 네이티브를 사용하고 있습니다.저는 다음과 같은 구조의 부품을 가지고 있습니다.

component
    - component.ios.tsx
    - component.android.tsx

이제 구성 요소를 가져오려고 합니다.그래서, 저는 이렇게 하고 있습니다.

import component from '../component/component';

하지만 다음과 같습니다.

[ts] Cannot find module ../component/component

위치가 맞습니다.나는 그것을 이해하기 위해 tslint 파일에 무언가를 추가해야 합니다.

저도 노력했습니다.

let component = require('../component/component');

이것은 타자기 오류를 일으키지 않았습니다.하지만 런타임 오류가 발생했습니다.

element type is invalid expected a string or a class/function but got undefined

이 문제에 부딪힌 사람이 있습니까?감사해요.

이 작업의 한 가지 방법은 약간 성가신 것이지만, 같은 이름의 선언 파일을 만드는 것입니다.

component
- component.d.ts   <---
- component.android.tsx
- component.ios.tsx

그리고나서

import { file } from "../group/file";

업데이트: 또 다른 방법은 확장자 중 하나를 생략하는 것입니다. 그러면 유형 스크립트에서 기본 확장자를 선택합니다.

  • 구성 요소.tsx
  • 구성 요소.vmdk.tsx

Android는 특정 Android 파일을 선택하고 iOS는 기본적으로 일반 파일로 설정됩니다.

React의 마지막 버전에서는 Sussion과 Lazy사용하여 과도한 입력 등을 피할 수 있습니다. 예를 들어 iOS 및 Android용 특정 코드가 포함된 Touchable 구성 요소를 원하는 경우 제 구조는 다음과 같습니다.

- Touchable
   - index.tsx
   - Touchable.android.tsx
   - Touchable.ios.tsx
   - types.d.ts
   

그리고 index.tsx의 코드는 다음과 같습니다.

import React, { FunctionComponent, lazy, Suspense } from 'react';
import { Platform, View } from 'react-native';

import { TouchableProps } from './types.d';

const TouchableComponent = lazy(() =>
  Platform.OS === 'ios'
    ? import('./Touchable.ios')
    : import('./Touchable.android'),
);

const Touchable: FunctionComponent<TouchableProps> = (props) => {
  return (
    <Suspense fallback={<View />}>
      <TouchableComponent {...props} />
    </Suspense>
  );
};

export default Touchable;

따라서 앱에서 이 구성 요소를 사용하려면 어디서나 다음 작업을 수행해야 합니다.

import Touchable from './path/to/Touchable';

[...]
<Touchable>
  <Text>Touchable text</Text>
</Touchable>
[...]

유형.d.ts:

export type TouchableSizeType = 'small' | 'regular' | 'big';
export type TouchableType = 'primary' | 'secondary' | 'success' | 'error' | 'warning';

export interface TouchableProps {
  disabled?: boolean;
  size?: TouchableSizeType;
  type?: TouchableType;
  onClick?: (event?: Event) => Promise<void>;
}

구성 요소 이름이 ProgressBar라고 가정하고 다음을 생성합니다.index.d.ts그리고 아래의 index.d.ts에서 코드를 조정합니다.

import {Component} from 'react';
import {Constructor, NativeMethodsMixin} from 'react-native';

export interface ProgressBarProps {
  progress: number;
}

declare class ProgressBarComponent extends Component<ProgressBarProps> {}

declare const ProgressBarBase: Constructor<NativeMethodsMixin> &
  typeof ProgressBarComponent;

export default class ProgressBar extends ProgressBarBase {}

따라서 구성 요소 폴더는 다음과 같아야 합니다.

component/
 - index.android.tsx
 - index.ios.tsx
 - index.d.ts

모든 것이 말이 됩니다, 파일이 다음 위치에 있기 때문에.../component/component.tsx존재하지 않습니다.

시도해 본 적은 없지만, 이것은 TS가 그러한 수입을 이해하는 것을 배울 수 있습니다.

{
    "compilerOptions": {
        "paths": {
            "*": ["*", "*.ios", "*.android"]
        }
   }
}

tsconfig.json 파일에 다음 행 추가

"moduleSuffixes": [".ios", ".android", ".native", ""],

부품의 소비자가 여전히 잘못된 것을 수입할 수 있기 때문에 최선의 해결책은 아니지만 올바른 방향으로 나아가는 단계입니다.우리 메트로 번들러는 적절한 파일을 찾을 수 있고 유형 안전을 얻을 수 있습니다.

폴더

  • 플랫폼 이미지
    • index.tsx
    • PlatformImage.android.tsx
    • 플랫폼 이미지.d.ts
    • PlatformImage.ios.

Testing.tsx

import React from 'react';
import { StyleSheet } from 'react-native';
import PlatformImage from '/ui/corex/PlatformImage';

const Testing = () => {
  return (
    <PlatformImage
      style={styles.prefixImage}
      borderRadius={styles.prefixImage.borderRadius}
      source={{
        uri: 'my uri',
        priority: 'high',
      }}
    />
  );
};

const styles = StyleSheet.create({
  prefixImage: {
    resizeMode: 'contain',
    width: '100%',
    height: '100%',
    borderRadius: 40,
  },
});

export default Testing;

플랫폼 이미지.d.ts

import { ImageStyle, StyleProp } from 'react-native';
import { Priority } from 'react-native-fast-image';

/**
 * An restricted list of props as we don't currently want to overcomplicate the code by supporting more
 * props than we actually need. If we need specific props that are supported by react-native.Image or
 * react-native-fast-image, we can add them as we need them.
 */
export interface PlatformImageProps {
  testID?: string;
  style?: StyleProp<ImageStyle>;
  source: {
    uri: string;
    /**
     * Only used in ios
     */
    priority: Priority;
  };
  /**
   *
   * Only used on android for border radius (since styles.borderRadius doesn't work for android). For ios, specify in styles.
   * Ideally the api for this component should be the same for both android & ios,
   * but this would mean preventing a styles.borderRadius from being used in ios in favor of using the
   * borderRadius prop, but this could be messy to code & maintain.
   */
  borderRadius?: number;
  resizeMode?: 'contain' | 'cover' | 'stretch' | 'center';
  /**
   * Invoked when load either succeeds or fails
   */
  onLoadEnd?: () => void;
}

declare const PlatformImage: React.ComponentType<PlatformImageProps>;

export default PlatformImage;

index.tsx

import PlatformImage from '/ui/corex/PlatformImage/PlatformImage';

export default PlatformImage;

PlatformImage.android.tsx

import React from 'react';
import { Image } from 'react-native';
import { PlatformImageProps } from '/ui/corex/PlatformImage/PlatformImage';

/**
 * Components should never import this directly, but should rather import the index.tsx file
 */
const PlatformImage = ({
  testID,
  style,
  source,
  resizeMode = 'cover',
  borderRadius,
  onLoadEnd,
}: PlatformImageProps) => {
  console.log('running android');
  return (
    <Image
      testID={testID}
      // todo simon: fix this typescript error
      style={style}
      resizeMode={resizeMode}
      borderRadius={borderRadius}
      onLoadEnd={onLoadEnd}
      source={source}
    />
  );
};

export default PlatformImage;

PlatformImage.ios.

import React from 'react';
import FastImage from 'react-native-fast-image';
import { PlatformImageProps } from '/ui/corex/PlatformImage/PlatformImage';

/**
 * Components should never import this directly, but should rather import the index.tsx file
 */
const PlatformImage = ({
  testID,
  style,
  source,
  resizeMode = 'cover',
  onLoadEnd,
}: PlatformImageProps) => {
  console.log('running ios');
  return (
    <FastImage
      testID={testID}
      // todo simon: fix this typescript error
      style={style}
      resizeMode={resizeMode}
      onLoadEnd={onLoadEnd}
      source={source}
    />
  );
};

export default PlatformImage;

실수하기 쉬운 가져오기.vcode가 어떻게 많은 수입품을 제안하는지 주목하세요. 하지만 우리는 단지 해야만 합니다.import PlatformImage from '/ui/corex/PlatformImage';

enter image description here

언급URL : https://stackoverflow.com/questions/44001050/platform-specific-import-component-in-react-native-with-typescript

반응형