来自组件的反应导航与博览会

Posted

技术标签:

【中文标题】来自组件的反应导航与博览会【英文标题】:React Navigation from Component with expo 【发布时间】:2020-04-23 06:09:24 【问题描述】:

我正在尝试从另一个主要从屏幕调用的组件内部使用 React Navigation。 层次结构:登录屏幕有一个按钮组件,该组件设计了一个 TouchableOpacity 组件,并且该登录按钮应该调用另一个屏幕 Home。

login.js

import React,  Component  from "react";
import  StyleSheet, View, Text, Button  from "react-native";
import  withNavigation  from 'react-navigation';
import CupertinoButtonSuccess from "../components/CupertinoButtonSuccess";
import CupertinoButtonWarning1 from "../components/CupertinoButtonWarning1";
import MaterialIconTextbox from "../components/MaterialIconTextbox";

//function Login(props) 
  export default class Login extends Component 
    static navigationOptions = 
      headerShown: false
    ;

    render() 
  return (
    <View style=styles.container>
      <Text style=styles.coMproTech1>COMproTECH</Text>
      <View style=styles.rectStack>
        <View style=styles.rect>
          <CupertinoButtonSuccess
            Navigation=this.props.navigation
            text1="Login"
            style=styles.cupertinoButtonSuccess
          ></CupertinoButtonSuccess>
          <CupertinoButtonWarning1
            text1="Forgot Password"
            style=styles.cupertinoButtonWarning1
          ></CupertinoButtonWarning1>
          <Button  title='test' onPress=this.handleClick></Button>
        </View>
        <View style=styles.rect2></View>
        <MaterialIconTextbox
          textInput1="Enter email"
          icon1Name="account"
          style=styles.materialIconTextbox
        ></MaterialIconTextbox>
        <MaterialIconTextbox
          icon1Name="account-key"
          textInput1="Password"
          style=styles.materialIconTextbox2
        ></MaterialIconTextbox>
      </View>
      <Text style=styles.services1>Services</Text>
    </View>
  );

  

const styles = StyleSheet.create(
  container: 
    flex: 1,
    backgroundColor: "rgba(74,144,226,1)"
  ,
  coMproTech1: 
    color: "rgba(247,242,242,1)",
    fontSize: 36,
    fontFamily: "Cochin-BoldItalic",
    marginTop: 110,
    marginLeft: 16
  ,
  rect: 
    top: 19,
    left: 0,
    width: 342,
    height: 319,
    backgroundColor: "rgba(255,255,255,1)",
    position: "absolute",
    borderRadius: 20,
    borderBottomRightRadius: 20
  ,
  cupertinoButtonSuccess: 
    width: 65,
    height: 39,
    borderRadius: 6,
    marginTop: 200,
    marginLeft: 261
  ,
  cupertinoButtonWarning1: 
    width: 167,
    height: 44,
    borderRadius: 10,
    marginTop: 9,
    marginLeft: 159
  ,
  rect2: 
    top: 0,
    left: 48,
    width: 42,
    height: 42,
    backgroundColor: "rgba(255,255,255,1)",
    position: "absolute",
    transform: [
      
        rotate: "45.00deg"
      
    ],
    borderRadius: 7
  ,
  materialIconTextbox: 
    top: 59,
    left: 0,
    width: 343,
    height: 48,
    position: "absolute"
  ,
  materialIconTextbox2: 
    top: 141,
    left: 0,
    width: 343,
    height: 48,
    position: "absolute"
  ,
  rectStack: 
    width: 343,
    height: 338,
    marginTop: 125,
    marginLeft: 16
  ,
  services1: 
    color: "rgba(247,242,242,1)",
    fontSize: 36,
    fontFamily: "Cochin-BoldItalic",
    marginTop: -450,
    marginLeft: 18
  
);

//export default Login;

CupertinoSuccess.js

import React,  Component  from "react";
import  StyleSheet, TouchableOpacity, Text, Button  from "react-native";
import  withNavigation  from 'react-navigation';
import  NavigationInjectedProps  from 'react-navigation';
import  createStackNavigator  from "react-navigation-stack";


function CupertinoButtonSuccess(props) 
  return (
    <TouchableOpacity
    onPress=() => this.props.navigation.goBack()
    style=[styles.container, props.style]>
      <Text style=styles.caption>props.text1 || "Button"</Text>
    </TouchableOpacity>
  );


const styles = StyleSheet.create(
  container: 
    backgroundColor: "#4CD964",
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    paddingRight: 12,
    paddingLeft: 12,
    borderRadius: 5
  ,
  caption: 
    color: "#fff",
    fontSize: 17,
    //fontFamily: "Cochin-BoldItalic"
  
);

export default CupertinoButtonSuccess;

得到错误/异常:

undefined object 'this.props'

TypeError: undefined is not an object (evaluating '_this.props')

createReactClass$argument_0.touchableHandlePress
    D:\android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Components\Touchable\TouchableOpacity.js:264:45
touchableHandlePress
    [native code]:0
TouchableMixin._performSideEffectsForTransition
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Components\Touchable\Touchable.js:880:34
_performSideEffectsForTransition
    [native code]:0
TouchableMixin._receiveSignal
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Components\Touchable\Touchable.js:779:44
_receiveSignal
    [native code]:0
TouchableMixin.touchableHandleResponderRelease
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Components\Touchable\Touchable.js:490:24
touchableHandleResponderRelease
    [native code]:0
invokeGuardedCallbackImpl
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:307:15
invokeGuardedCallback
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:531:36
invokeGuardedCallbackAndCatchFirstError
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:555:30
executeDispatch
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:722:42
executeDispatchesInOrder
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:744:20
executeDispatchesAndRelease
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:907:29
forEach
    [native code]:0
forEachAccumulated
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:887:16
runEventsInBatch
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:932:21
runExtractedPluginEventsInBatch
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:1096:19
batchedUpdates$argument_0
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2796:6
batchedUpdates$1
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:18791:14
batchedUpdates
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2709:30
batchedUpdates$argument_0
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2794:17
receiveTouches
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\Renderer\implementations\ReactNativeRenderer-dev.js:2870:28
__callFunction
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:436:47
__guard$argument_0
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:111:26
__guard
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:384:10
__guard$argument_0
    D:\Android Projects\React_Projects\SplashNav\snav\node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:110:17
callFunctionReturnFlushedQueue
    [native code]:0

【问题讨论】:

您好,先生,已更新错误日志。 【参考方案1】:

您有一个带有props 参数的函数组件:

function CupertinoButtonSuccess(props) 
  // ...

在里面,你正在使用this.props.navigation.goBack()。但是this.props在函数组件中不可用。您需要将其更改为使用props.navigation.goBack()(不带this)。

【讨论】:

嗨,先生,我是新来的本地人,你能帮我解决这个问题吗?我试过没有“这个”。但也没有工作,我如何将函数 CupertinoButtonSuccess(props) 更改为类 CupertinoButton 因为当我尝试时,它说未定义的道具。 如果你是 React Native 新手,你应该阅读官方 React 文档并熟悉 React【参考方案2】:

关于反应导航,尤其是您正在使用的堆栈导航,您需要了解一些事情。当前版本是导航5。

它允许您在作为组件传递的屏幕之间导航 下到反应导航的文件,让我们调用那个配置文件 应用程序.js。在您的情况下,您的屏幕是“主页”和“登录”,其中 意味着您应该拥有 Home.js 和 Login.js 组件或 在你的项目中设置的函数。

//这是 App.js 的最低配置 // 注意,'@' 对导航很重要 5

import React from 'react';
import  createStackNavigator  from '@react-navigation/stack';
import  NavigationContainer  from '@react-navigation/native';
import Home from './Home';
import Login from './Login';

const Stack  = createStackNavigator();

export default class App extends React.Component 

 render() 
    return (
      <NavigationContainer>
        <Stack.Navigator initialRouteName='Home'>
           <Stack.Screen name='Home'    component=Home />
           <Stack.Screen name='Login'   component=Login />
        </Stack.Navigator>
      </NavigationContainer>
    );
  

你的 Login.js 组件和你做的一样,但是你应该将导航道具传递给 CupertinoButtonSuccess 和 CupertinoButtonWarnings,否则它们无法自动访问导航道具,因为你没有在导航配置文件中将它们定义为屏幕。为此,您只需在 Login.js 的 render 方法中使用它

render() 
  return(
 <CupertinoButtonSuccess navigation=navigation /> 
 <CupertinoButtonWarning1 navigation=navigation /> 
);

而不是

render()
return(
<CupertinoButtonSuccess Navigation=this.props.navigation
           ... > </CupertinoButtonSuccess>
<cupertinoButtonWarning1 Navigation=this.props.navigation
           ... >
</cupertinoButtonWarning1> 
);

(您甚至永远不会在 react native 中关闭像这样的自定义组件。只有内置​​的 react native 组件,例如我们的 View,Text 具有关闭标签,例如 "&lt;View&gt;&lt;/View&gt;""&lt;Text&gt;&lt;/Text&gt;", 但这是一个自定义组件,因为它只属于你,而不是所有反应原生开发者。另外,您导入的“CupertinoButtonWarning1”以大写字母“C”开头,现在将其称为“cupertinoButtonWarning1”是另一个错误,但我希望这只是输入错误。

现在关于如何制作 CupertinoButtonSuccess 类组件而不是基于函数的组件,您将需要创建两个基于类的组件,一个用于 CupertinoButtonSuccess.js,第二个用于 CupertinoButtonWarning1.js,因为您无法从相同的单个组件。

// 所以对于 CupertinoButtonSuccess.js

import React,  Component  from "react";
import  StyleSheet, TouchableOpacity, Text, Button  from "react-native";
//You never need to be calling  createStackNavigator  here again because //CupertinoButtonSuccess.js is not a screen
 export default class CupertinoButtonSuccess extends Component 
   render()
       return (
    <TouchableOpacity
    onPress=() => this.props.navigation.goBack('Home')
    style=[styles.container, props.style]>
      <Text style=styles.caption>props.text1 || "Button"</Text>
    </TouchableOpacity>
  );


const styles = StyleSheet.create(
   //Your style here
);

//对于 CupertinoButtonWarning1.js 你也这样做。

最后,为了完整起见,还有另一种方法可以直接在 CupertinoButtonSuccess.js 和 CupertinoButtonWarning1 中使用导航道具,而无需等待 Loging.js 将其传递给它们,它是通过像这样导入“useNavigation” CupertinoButtonSuccess.js 和 CupertinoButtonWarning1.js :

import  useNavigation  from '@react-navigation/native';

这样,您甚至可以从 CupertinoButtonSuccess.js 和 CupertinoButtonWarning1.js 访问导航道具。 关于这个的文档在这里https://reactnavigation.org/docs/connecting-navigation-prop/

【讨论】:

以上是关于来自组件的反应导航与博览会的主要内容,如果未能解决你的问题,请参考以下文章

从窗口组件反应导航全屏模式

如何在反应博览会中显示数据库中的图像

暂停反应原生博览会音频?

分享扩展反应原生 - 博览会

反应原生博览会。 Android暗模式问题

在按钮上打开相机点击反应原生博览会