【问题标题】:Platform specific import component in react native with typescript与打字稿反应本机的平台特定导入组件
【发布时间】:2017-10-15 12:16:03
【问题描述】:

我正在使用带有 typescript 的 react native。我有一个具有以下结构的组件

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

有人遇到过这个问题吗? 谢谢。

【问题讨论】:

    标签: typescript react-native


    【解决方案1】:

    一种有点烦人的方法是创建一个同名的声明文件。

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

    然后

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

    更新: 另一种方法是省略其中一个的扩展名,然后 typescript 会选择默认的。

    • component.tsx
    • component.android.tsx

    Android 会选择特定的 android 文件,iOS 会默认为普通文件。

    【讨论】:

      【解决方案2】:

      使用最新版本的 React,您可以使用 Suspenselazy 来避免过度输入等,例如,如果我想要一个组件 Touchable使用 iOS 和 Android 的特定代码,我的结构将如下所示:

      - 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>
      [...]
      

      Types.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>;
      }
      

      【讨论】:

      • types.d.ts 应该是什么样子?
      • 我刚刚编辑了回复以添加 types.d.ts 文件的示例,希望对您有所帮助
      • 好的,这工作正常......我喜欢它......你有什么问题吗?我很担心,因为悬念(仍然)是实验性的......
      【解决方案3】:

      假设您的组件名称是 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
      

      【讨论】:

      • 感谢您的成功!其他答案让我很困惑,呵呵。对于那些不明白的人,filename.d.ts 基本上是 TypeScript 在您尝试导入时确定类型时会查看的文件。因此,在该文件中,只需为您要导出的内容导出正确的类型(无论可能是什么),然后 TypeScript 就会得到满足,停止抱怨,并正确键入您的导入。
      【解决方案4】:

      这一切都说得通,因为../component/component.tsx 的文件不存在。

      没试过,不过这个可以学习TS理解这样的导入

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

      【讨论】:

      • 它对我不起作用。 TypeScript 3.3 和 VSCode 1.45
      猜你喜欢
      • 2018-11-17
      • 2020-11-18
      • 2017-12-04
      • 2020-03-28
      • 2021-10-04
      • 1970-01-01
      • 2017-11-28
      • 2020-04-02
      • 1970-01-01
      相关资源
      最近更新 更多