为啥我不能在 react native 中导入我的自定义组件

Posted

技术标签:

【中文标题】为啥我不能在 react native 中导入我的自定义组件【英文标题】:why can't i import my custom component in react native为什么我不能在 react native 中导入我的自定义组件 【发布时间】:2021-06-07 08:54:11 【问题描述】:

我创建了这些组件,我试图在 App.js 中导入它们,但它向我显示一条错误消息,我试图多次更改导出默认类,我改变了导入行的顺序以确定是否存在' e 导入其中一个组件时出错,但没有任何改变,仍然显示相同的错误消息,我该如何修复它

App.js

import React,  Component  from "react";
import ActivityIndicator,Keyboard,KeyboardAvoidingView,StyleSheet from "react-native";

import  theme  from './constants';
import  Block from './app/components' ; 
import  Button from './app/components' ; 
import  Text from './app/components' ; 
import  Input from './app/components' ; 

const VALID_EMAIL = "contact@react-ui-kit.com";
const VALID_PASSWORD = "subscribe";

export default class Login extends Component 
  state = 
    email: VALID_EMAIL,
    password: VALID_PASSWORD,
    errors: [],
    loading: false
  ;

  handleLogin() 
    const  navigation  = this.props;
    const  email, password  = this.state;
    const errors = [];

    Keyboard.dismiss();
    this.setState( loading: true );

    // check with backend API or with some static data
    if (email !== VALID_EMAIL) 
      errors.push("email");
    
    if (password !== VALID_PASSWORD) 
      errors.push("password");
    

    this.setState( errors, loading: false );

    if (!errors.length) 
      navigation.navigate("Browse");
    
  

  render() 
    const  navigation  = this.props;
    const  loading, errors  = this.state;
    const hasErrors = key => (errors.includes(key) ? styles.hasErrors : null);

    return (
      <KeyboardAvoidingView style=styles.login behavior="padding">
        <Block padding=[0, theme.sizes.base * 2]>
          <Text h1 bold>
            Login
          </Text>
          <Block middle>
            <Input
              label="Email"
              error=hasErrors("email")
              style=[styles.input, hasErrors("email")]
              defaultValue=this.state.email
              onChangeText=text => this.setState( email: text )
            />
            <Input
              secure
              label="Password"
              error=hasErrors("password")
              style=[styles.input, hasErrors("password")]
              defaultValue=this.state.password
              onChangeText=text => this.setState( password: text )
            />
            <Button gradient onPress=() => this.handleLogin()>
              loading ? (
                <ActivityIndicator size="small" color="white" />
              ) : (
                <Text bold white center>
                  Login
                </Text>
              )
            </Button>

            <Button onPress=() => navigation.navigate("Forgot")>
              <Text
                gray
                caption
                center
                style= textDecorationLine: "underline" 
              >
                Forgot your password?
              </Text>
            </Button>
          </Block>
        </Block>
      </KeyboardAvoidingView>
    );
  


const styles = StyleSheet.create(
  login: 
    flex: 1,
    justifyContent: "center"
  ,
  input: 
    borderRadius: 0,
    borderWidth: 0,
    borderBottomColor: theme.colors.gray2,
    borderBottomWidth: StyleSheet.hairlineWidth
  ,
  hasErrors: 
    borderBottomColor: theme.colors.accent
  
);

Block.js

import React,  Component  from "react";
import  StyleSheet, View, Animated  from "react-native";

import  theme  from "./constants";

export default class Block extends Component 
  handleMargins() 
    const  margin  = this.props;
    if (typeof margin === "number") 
      return 
        marginTop: margin,
        marginRight: margin,
        marginBottom: margin,
        marginLeft: margin
      ;
    

    if (typeof margin === "object") 
      const marginSize = Object.keys(margin).length;
      switch (marginSize) 
        case 1:
          return 
            marginTop: margin[0],
            marginRight: margin[0],
            marginBottom: margin[0],
            marginLeft: margin[0]
          ;
        case 2:
          return 
            marginTop: margin[0],
            marginRight: margin[1],
            marginBottom: margin[0],
            marginLeft: margin[1]
          ;
        case 3:
          return 
            marginTop: margin[0],
            marginRight: margin[1],
            marginBottom: margin[2],
            marginLeft: margin[1]
          ;
        default:
          return 
            marginTop: margin[0],
            marginRight: margin[1],
            marginBottom: margin[2],
            marginLeft: margin[3]
          ;
      
    
  

  handlePaddings() 
    const  padding  = this.props;
    if (typeof padding === "number") 
      return 
        paddingTop: padding,
        paddingRight: padding,
        paddingBottom: padding,
        paddingLeft: padding
      ;
    

    if (typeof padding === "object") 
      const paddingSize = Object.keys(padding).length;
      switch (paddingSize) 
        case 1:
          return 
            paddingTop: padding[0],
            paddingRight: padding[0],
            paddingBottom: padding[0],
            paddingLeft: padding[0]
          ;
        case 2:
          return 
            paddingTop: padding[0],
            paddingRight: padding[1],
            paddingBottom: padding[0],
            paddingLeft: padding[1]
          ;
        case 3:
          return 
            paddingTop: padding[0],
            paddingRight: padding[1],
            paddingBottom: padding[2],
            paddingLeft: padding[1]
          ;
        default:
          return 
            paddingTop: padding[0],
            paddingRight: padding[1],
            paddingBottom: padding[2],
            paddingLeft: padding[3]
          ;
      
    
  

  render() 
    const 
      flex,
      row,
      column,
      center,
      middle,
      left,
      right,
      top,
      bottom,
      card,
      shadow,
      color,
      space,
      padding,
      margin,
      animated,
      wrap,
      style,
      children,
      ...props
     = this.props;

    const blockStyles = [
      styles.block,
      flex &&  flex ,
      flex === false &&  flex: 0 , // reset / disable flex
      row && styles.row,
      column && styles.column,
      center && styles.center,
      middle && styles.middle,
      left && styles.left,
      right && styles.right,
      top && styles.top,
      bottom && styles.bottom,
      margin &&  ...this.handleMargins() ,
      padding &&  ...this.handlePaddings() ,
      card && styles.card,
      shadow && styles.shadow,
      space &&  justifyContent: `space-$space` ,
      wrap &&  flexWrap: "wrap" ,
      color && styles[color], // predefined styles colors for backgroundColor
      color && !styles[color] &&  backgroundColor: color , // custom backgroundColor
      style // rewrite predefined styles
    ];

    if (animated) 
      return (
        <Animated.View style=blockStyles ...props>
          children
        </Animated.View>
      );
    

    return (
      <View style=blockStyles ...props>
        children
      </View>
    );
  


export const styles = StyleSheet.create(
  block: 
    flex: 1
  ,
  row: 
    flexDirection: "row"
  ,
  column: 
    flexDirection: "column"
  ,
  card: 
    borderRadius: theme.sizes.radius
  ,
  center: 
    alignItems: "center"
  ,
  middle: 
    justifyContent: "center"
  ,
  left: 
    justifyContent: "flex-start"
  ,
  right: 
    justifyContent: "flex-end"
  ,
  top: 
    justifyContent: "flex-start"
  ,
  bottom: 
    justifyContent: "flex-end"
  ,
  shadow: 
    shadowColor: theme.colors.black,
    shadowOffset:  width: 0, height: 2 ,
    shadowOpacity: 0.1,
    shadowRadius: 13,
    elevation: 2
  ,
  accent:  backgroundColor: theme.colors.accent ,
  primary:  backgroundColor: theme.colors.primary ,
  secondary:  backgroundColor: theme.colors.secondary ,
  tertiary:  backgroundColor: theme.colors.tertiary ,
  black:  backgroundColor: theme.colors.black ,
  white:  backgroundColor: theme.colors.white ,
  gray:  backgroundColor: theme.colors.gray ,
  gray2:  backgroundColor: theme.colors.gray2 
);

Text.js

import React,  Component  from "react";
import  Text, StyleSheet  from "react-native";

import  theme  from "./constants";

export default class Typography extends Component 
  render() 
    const 
      h1,
      h2,
      h3,
      title,
      body,
      caption,
      small,
      size,
      transform,
      align,
      // styling
      regular,
      bold,
      semibold,
      medium,
      weight,
      light,
      center,
      right,
      spacing, // letter-spacing
      height, // line-height
      // colors
      color,
      accent,
      primary,
      secondary,
      tertiary,
      black,
      white,
      gray,
      gray2,
      style,
      children,
      ...props
     = this.props;

    const textStyles = [
      styles.text,
      h1 && styles.h1,
      h2 && styles.h2,
      h3 && styles.h3,
      title && styles.title,
      body && styles.body,
      caption && styles.caption,
      small && styles.small,
      size &&  fontSize: size ,
      transform &&  textTransform: transform ,
      align &&  textAlign: align ,
      height &&  lineHeight: height ,
      spacing &&  letterSpacing: spacing ,
      weight &&  fontWeight: weight ,
      regular && styles.regular,
      bold && styles.bold,
      semibold && styles.semibold,
      medium && styles.medium,
      light && styles.light,
      center && styles.center,
      right && styles.right,
      color && styles[color],
      color && !styles[color] &&  color ,
      // color shortcuts
      accent && styles.accent,
      primary && styles.primary,
      secondary && styles.secondary,
      tertiary && styles.tertiary,
      black && styles.black,
      white && styles.white,
      gray && styles.gray,
      gray2 && styles.gray2,
      style // rewrite predefined styles
    ];

    return (
      <Text style=textStyles ...props>
        children
      </Text>
    );
  


const styles = StyleSheet.create(
  // default style
  text: 
    fontSize: theme.sizes.font,
    color: theme.colors.black
  ,
  // variations
  regular: 
    fontWeight: "normal"
  ,
  bold: 
    fontWeight: "bold"
  ,
  semibold: 
    fontWeight: "500"
  ,
  medium: 
    fontWeight: "500"
  ,
  light: 
    fontWeight: "200"
  ,
  // position
  center:  textAlign: "center" ,
  right:  textAlign: "right" ,
  // colors
  accent:  color: theme.colors.accent ,
  primary:  color: theme.colors.primary ,
  secondary:  color: theme.colors.secondary ,
  tertiary:  color: theme.colors.tertiary ,
  black:  color: theme.colors.black ,
  white:  color: theme.colors.white ,
  gray:  color: theme.colors.gray ,
  gray2:  color: theme.colors.gray2 ,
  // fonts
  h1: theme.fonts.h1,
  h2: theme.fonts.h2,
  h3: theme.fonts.h3,
  title: theme.fonts.title,
  body: theme.fonts.body,
  caption: theme.fonts.caption,
  small: theme.fonts.small
);

Button.js

import React,  Component  from "react";
import  StyleSheet, TouchableOpacity  from "react-native";
import  LinearGradient  from "react-native-linear-gradient";
import  theme  from "./constants";

class Button extends Component 
  render() 
    const 
      style,
      opacity,
      gradient,
      color,
      startColor,
      endColor,
      end,
      start,
      locations,
      shadow,
      children,
      ...props
     = this.props;

    const buttonStyles = [
      styles.button,
      shadow && styles.shadow,
      color && styles[color], // predefined styles colors for backgroundColor
      color && !styles[color] &&  backgroundColor: color , // custom backgroundColor
      style
    ];

    if (gradient) 
      return (
        <TouchableOpacity
          style=buttonStyles
          activeOpacity=opacity
          ...props
        >
          <LinearGradient
            start=start
            end=end
            locations=locations
            style=buttonStyles
            colors=[startColor, endColor]
          >
            children
          </LinearGradient> */
        </TouchableOpacity>
      );
    

    return (
      <TouchableOpacity
        style=buttonStyles
        activeOpacity=opacity || 0.8
        ...props
      >
        children
      </TouchableOpacity>
    );
  


Button.defaultProps = 
  startColor: theme.colors.primary,
  endColor: theme.colors.secondary,
  start:  x: 0, y: 0 ,
  end:  x: 1, y: 1 ,
  locations: [0.1, 0.9],
  opacity: 0.8,
  color: theme.colors.white
;

export default Button;

const styles = StyleSheet.create(
  button: 
    borderRadius: theme.sizes.radius,
    height: theme.sizes.base * 3,
    justifyContent: "center",
    marginVertical: theme.sizes.padding / 3
  ,
  shadow: 
    shadowColor: theme.colors.black,
    shadowOffset:  width: 0, height: 2 ,
    shadowOpacity: 0.1,
    shadowRadius: 10
  ,
  accent:  backgroundColor: theme.colors.accent ,
  primary:  backgroundColor: theme.colors.primary ,
  secondary:  backgroundColor: theme.colors.secondary ,
  tertiary:  backgroundColor: theme.colors.tertiary ,
  black:  backgroundColor: theme.colors.black ,
  white:  backgroundColor: theme.colors.white ,
  gray:  backgroundColor: theme.colors.gray ,
  gray2:  backgroundColor: theme.colors.gray2 ,
  gray3:  backgroundColor: theme.colors.gray3 ,
  gray4:  backgroundColor: theme.colors.gray4 
);

Input.js

import React,  Component  from "react";
import  StyleSheet, View, Animated  from "react-native";

import  theme  from "./constants";

export default class Block extends Component 
  handleMargins() 
    const  margin  = this.props;
    if (typeof margin === "number") 
      return 
        marginTop: margin,
        marginRight: margin,
        marginBottom: margin,
        marginLeft: margin
      ;
    

    if (typeof margin === "object") 
      const marginSize = Object.keys(margin).length;
      switch (marginSize) 
        case 1:
          return 
            marginTop: margin[0],
            marginRight: margin[0],
            marginBottom: margin[0],
            marginLeft: margin[0]
          ;
        case 2:
          return 
            marginTop: margin[0],
            marginRight: margin[1],
            marginBottom: margin[0],
            marginLeft: margin[1]
          ;
        case 3:
          return 
            marginTop: margin[0],
            marginRight: margin[1],
            marginBottom: margin[2],
            marginLeft: margin[1]
          ;
        default:
          return 
            marginTop: margin[0],
            marginRight: margin[1],
            marginBottom: margin[2],
            marginLeft: margin[3]
          ;
      
    
  

  handlePaddings() 
    const  padding  = this.props;
    if (typeof padding === "number") 
      return 
        paddingTop: padding,
        paddingRight: padding,
        paddingBottom: padding,
        paddingLeft: padding
      ;
    

    if (typeof padding === "object") 
      const paddingSize = Object.keys(padding).length;
      switch (paddingSize) 
        case 1:
          return 
            paddingTop: padding[0],
            paddingRight: padding[0],
            paddingBottom: padding[0],
            paddingLeft: padding[0]
          ;
        case 2:
          return 
            paddingTop: padding[0],
            paddingRight: padding[1],
            paddingBottom: padding[0],
            paddingLeft: padding[1]
          ;
        case 3:
          return 
            paddingTop: padding[0],
            paddingRight: padding[1],
            paddingBottom: padding[2],
            paddingLeft: padding[1]
          ;
        default:
          return 
            paddingTop: padding[0],
            paddingRight: padding[1],
            paddingBottom: padding[2],
            paddingLeft: padding[3]
          ;
      
    
  

  render() 
    const 
      flex,
      row,
      column,
      center,
      middle,
      left,
      right,
      top,
      bottom,
      card,
      shadow,
      color,
      space,
      padding,
      margin,
      animated,
      wrap,
      style,
      children,
      ...props
     = this.props;

    const blockStyles = [
      styles.block,
      flex &&  flex ,
      flex === false &&  flex: 0 , // reset / disable flex
      row && styles.row,
      column && styles.column,
      center && styles.center,
      middle && styles.middle,
      left && styles.left,
      right && styles.right,
      top && styles.top,
      bottom && styles.bottom,
      margin &&  ...this.handleMargins() ,
      padding &&  ...this.handlePaddings() ,
      card && styles.card,
      shadow && styles.shadow,
      space &&  justifyContent: `space-$space` ,
      wrap &&  flexWrap: "wrap" ,
      color && styles[color], // predefined styles colors for backgroundColor
      color && !styles[color] &&  backgroundColor: color , // custom backgroundColor
      style // rewrite predefined styles
    ];

    if (animated) 
      return (
        <Animated.View style=blockStyles ...props>
          children
        </Animated.View>
      );
    

    return (
      <View style=blockStyles ...props>
        children
      </View>
    );
  


export const styles = StyleSheet.create(
  block: 
    flex: 1
  ,
  row: 
    flexDirection: "row"
  ,
  column: 
    flexDirection: "column"
  ,
  card: 
    borderRadius: theme.sizes.radius
  ,
  center: 
    alignItems: "center"
  ,
  middle: 
    justifyContent: "center"
  ,
  left: 
    justifyContent: "flex-start"
  ,
  right: 
    justifyContent: "flex-end"
  ,
  top: 
    justifyContent: "flex-start"
  ,
  bottom: 
    justifyContent: "flex-end"
  ,
  shadow: 
    shadowColor: theme.colors.black,
    shadowOffset:  width: 0, height: 2 ,
    shadowOpacity: 0.1,
    shadowRadius: 13,
    elevation: 2
  ,
  accent:  backgroundColor: theme.colors.accent ,
  primary:  backgroundColor: theme.colors.primary ,
  secondary:  backgroundColor: theme.colors.secondary ,
  tertiary:  backgroundColor: theme.colors.tertiary ,
  black:  backgroundColor: theme.colors.black ,
  white:  backgroundColor: theme.colors.white ,
  gray:  backgroundColor: theme.colors.gray ,
  gray2:  backgroundColor: theme.colors.gray2 
);

错误

Error: Unable to resolve module ./components from C:\Users\DELL\wan_way_service_app\App.js:

None of these files exist:
  * components(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
  * components\index(.native|.android.js|.native.js|.js|.android.json|.native.json|.json|.android.ts|.native.ts|.ts|.android.tsx|.native.tsx|.tsx)
  3 |
  4 | import  theme  from './constants';
> 5 | import  Button from './components' ;
    |                      ^
  6 | import  Block from './components' ;
  7 | import  Text from './components' ;
  8 | import  Input from './components' ;

【问题讨论】:

【参考方案1】:

您是否正确导出了组件?

选项 1 - 如果您要为每个文件导出一个组件,则可以使用“导出默认值”示例:

export default Class ClassName = () => 
  return <View />;

并导入使用

import ClassName from './app/components'

选项 2 - 如果有多个组件,则必须以这种方式导出为常量

export Class ClassName = () => 
  return <View />;

export Class OtherClassName = () => 
  return <View />;

并导入使用

import ClassName, OtherClassName from './app/components'

这取决于创建文件夹结构的方式,默认情况下,对于更简洁的代码,理想情况如下:

myAwesomeProject
  src
   | components
   | |  ComponentOne
   | |  | index.js
   | |  ComponentTwo
   | |  | index.js

这样你就可以使用默认导出

【讨论】:

export default class Block extends Component render () 但在您的 Button 类中,您没有以这种方式导出请参阅您从 Button.js 发送的代码。如果您可以添加组件的完整代码,那将有所帮助 我阅读了有关导出默认类和导出类的答案,所以我尝试了它们,但它们都不起作用 编辑您的问题,并添加您的组件的完整代码,以便我们了解更多详情 现在检查一下兄弟

以上是关于为啥我不能在 react native 中导入我的自定义组件的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能运行我的 React Native 项目?

Nativebase React Native 为啥我不能在输入中传递一个数字

Python 问题在脚本中导入我的文件(不在控制台中)

如何在 ES6 项目中导入我的 npm 模块?

为啥我不能在 ios 设备上关闭并重新打开 react-native 调试?

为啥我不能在 Windows 上运行 react-native 应用程序