简体   繁体   English

如何为 react-native 本机 ui 组件创建打字稿类型定义?

[英]How do I create typescript type definitions for react-native native ui component?

Let us say that I have a react native native UI component like the one in this example .假设我有一个像本例中那样的本机 UI 组件。 How do I create a typescript type definition for it, like the ones that can be imported, for example with 'npm i @types/somelib'?如何为其创建打字稿类型定义,例如可以导入的类型定义,例如使用“npm i @types/somelib”? I didn't find explanations about how to do this in the documentation.我没有在文档中找到有关如何执行此操作的说明。

The idea is to be able to use the native component seamlessly in a react-native typescript project and for that I need to create the type definition for native components.这个想法是能够在 react-native typescript 项目中无缝使用本机组件,为此我需要为本机组件创建类型定义。 So, how do I create typescript type definitions for native components?那么,如何为原生组件创建 typescript 类型定义?

The iOS/objc side iOS/对象端

  • FoobarView.h: FoobarView.h:

    #ifndef FoobarView_h
    #define FoobarView_h
    #import <UIKit/UIKit.h>
    #import <Foundation/Foundation.h>
    @interface FoobarView : UITextView
    @property (nonatomic, assign) BOOL teste;
    @end
    #endif

  • FoobarView.m: FoobarView.m:

    #import "FoobarView.h"
    @implementation FoobarView
    -(void) setTeste:(BOOL)teste
    {
      if (teste == YES)
      {
        [self setText:@"é true"];
      }else
      {
        [self setText:@"é false"];
      }
    }
    -(BOOL)getTeste
    {
      if ([[self text] isEqual:@"é true"])
      {
        return YES;
      }else
      {
        return NO;
      }
    }
    @end

  • FoobarManager.m FoobarManager.m

    #import <Foundation/Foundation.h>
    #import <React/RCTViewManager.h>
    #import "FoobarView.h"
    @interface FooManager : RCTViewManager
    @end
    @implementation FooManager
    RCT_EXPORT_MODULE(FoobarView)
    RCT_EXPORT_VIEW_PROPERTY(teste, BOOL)
    +(BOOL) requiresMainQueueSetup
    {
      return YES;
    }
    - (UIView*)view
    {
      FoobarView *v = [[FoobarView alloc]init];
      return v;
    }
    @end

So, FoobarView is a native iOS view, written in objc.所以,FoobarView 是一个原生的 iOS 视图,用 objc 编写。 It is not a react native ui component.它不是本机 ui 组件。 I am using a simple descendent from UITextView but it could be anything, like a SceneKit view.我使用的是 UITextView 的简单后代,但它可以是任何东西,比如 SceneKit 视图。

To use it in the javascript side of react native, I'm using this code in FoobarView.js:为了在 react native 的 javascript 端使用它,我在 FoobarView.js 中使用了这段代码:

import { requireNativeComponent } from 'react-native';
module.exports = requireNativeComponent('FoobarView');

And, finally, i can use FoobarView in a render block:最后,我可以在渲染块中使用 FoobarView:

    <FoobarView style={{width:'100%', height:30}} teste={true} />

My question is: How can I define that FoobarView, something defined in the ios, has the property teste, and that teste is a boolean?我的问题是:如何定义在 ios 中定义的 FoobarView 具有属性 teste,而 teste 是布尔值?

I guess for the topic starter my answer is a bit late but for everyone else who's facing the same issue I solved it with this approach:我想对于主题启动器,我的回答有点晚,但对于面临相同问题的其他人,我用这种方法解决了它:

import { requireNativeComponent, HostComponent } from 'react-native';

// Specify all your properties
interface Props {
  teste: boolean;
}

const FoobarView: HostComponent<Props> = requireNativeComponent('FoobarView');

module.exports = FoobarView;

TS will recognize only teste property but in your example you also pass style property to the component, so in order to support it as well you should either specify it explicitly in the Props above, eg TS 只会识别teste属性,但在您的示例中,您还将style属性传递给组件,因此为了支持它,您应该在上面的Props明确指定它,例如

interface Props {
  teste: boolean;
  style: ViewStyle;
}

Or you can extend View properties (if they're suitable for your usecase), eg或者您可以扩展 View 属性(如果它们适合您的用例),例如

interface Props extends ViewProps {
  teste: boolean;
}

So this is definitely a good read 所以绝对是一本好书

And here is an example of a component. 这是一个组件示例。

If you have the component like: 如果您有类似的组件:

// MapBox.js
import { requireNativeComponent } from ‘react-native’;
// requireNativeComponent automatically resolves this to “MapBoxManager”
module.exports = requireNativeComponent(‘MapBox’, null);

Just create the declaration file for that component. 只需为该组件创建声明文件。

something.js something.js

const React = require('react');


class Something extends React.Component {

  render() {

  }
}

module.exports = {
  Something,
}

something.d.ts 东西

import React from 'react';

export declare interface State {
  something: boolean;
}
export declare interface Props {
  argument: number;
}

export declare class Something extends React.Components<Props, State> {

  public render(): React.ReactNode;
}

Don't look too closely on the js I haven't worked with plain JavaScript in ages. 别看我很久没有使用纯JavaScript的js

For React native versions below 0.62对于低于 0.62 的 React 原生版本

Make sure to create .tsx file.确保创建 .tsx 文件。

//FoobarView.tsx

import React, { ReactElement } from 'react'
import { requireNativeComponent, ViewProps } from 'react-native'

interface Props extends ViewProps {
    teste: boolean
}
const _FoobarView = requireNativeComponent('FoobarView')

const FoobarView = (props: Props): ReactElement<Props> => {
    return <_FoobarView {...props} style={props.style} />
}

export default FoobarView

Inspired from: https://shopify.engineering/creating-native-components-accept-react-native-subviews灵感来自: https : //shopify.engineering/creating-native-components-accept-react-native-subviews

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM