如何创建带有子节点的自定义 React Native 组件

How to create custom React Native components with child nodes

我想创建一个纯 JavaScript 的 React Native 组件,由 TouchableOpacityText 等其他组件组成。我的应用程序中有几个按钮由这两个组件组成,所以我认为学习如何创建自己的组件以更好地重用代码会很好。

完成的组件应该大致如下所示:

<Button>
  Tap me!
</Button>

这是我目前为该组件编写的代码:

class Button extends Component {
  render () {
    <TouchableOpacity style={styles.button}>
      <Text style={styles.textButton}>
      </Text>
    </TouchableOpacity>
  }
};

但是,我不知道如何在我的组件中使用 Tap me! 内部子文本,我也不知道如何让我的组件接受自定义道具和 TouchableOpacityText 道具。

PS: 我知道有一些像这样的 React Native 组件,但我更喜欢创建自己的组件以学习如何构建它一种自定义组件。此外,React Native 很棒,但我在他们的文档中找不到如何构建这样的东西,我认为这对于开始使用 React 的人来说是一个非常有趣的练习。

您可以通过 this.props.children 访问内部文本,您可以手动(通过 this.props)或使用 ... 运算符传递属性。 react.js 文档中描述了更多内容(注意 - 不是 React Native 文档!)。文档中最相关的部分是:

React Native 文档的一般方法是不描述所有 React 概念,它们只描述 React Native 部分,实际概念在 React 的 web/original 版本中描述。

您可以从 github 查看此存储库:https://github.com/future-challenger/react-native-tabs

这里有一些代码:

<View style={[styles.tabbarView, this.props.style, this.state.keyboardUp && styles.hidden]}>
    {React.Children.map(this.props.children.filter(c=>c),(el)=>
    <TouchableOpacity key={el.props.name + "touch"}
        testID={el.props.testID}
        style={[styles.iconView, this.props.iconStyle, (el.props.name || el.key) == selected ? this.props.selectedIconStyle || el.props.selectedIconStyle || {} : {} ]}
        onPress={()=>!self.props.locked && self.onSelect(el)}
        onLongPress={()=>self.onSelect(el)}
        activeOpacity={el.props.pressOpacity}>
            {selected == (el.props.name || el.key) ? React.cloneElement(el, {selected: true, style: [el.props.style, this.props.selectedStyle, el.props.selectedStyle]}) : el}
    </TouchableOpacity>
)}

React.Children.map(this.props.children.filter...)是处理子组件的关键

对我来说,我只是将子项放入组件中,然后就此结束。还要记住,有时 iOS 和 Android 之间存在不同的实现。这是我刚刚写的并简要测试过的东西

import React, { FunctionComponent } from "react";
import { TouchableNativeFeedback, Platform, TouchableOpacity } from "react-native";


interface IAgnoButton {
    onPress: (item: any) => void,
    style: object
}

const AgnoButton: FunctionComponent<IAgnoButton> = (props) => {
    return (
        Platform.OS === 'android' ?
            <TouchableNativeFeedback
                onPress={props.onPress}
                style={{ ...props.style }}
                >
                { props.children }
            </TouchableNativeFeedback> :
            <TouchableOpacity
                onPress={props.onPress}
                style={{ ...props.style }}
                >
                { props.children }
            </TouchableOpacity>
    );
}
export default AgnoButton;