如何在屏幕外使用反应导航

问题描述 投票:2回答:2

当我正确输入代码时,我想让我的应用程序移动到下一页,但我这样做很麻烦。我正在使用文件名AccessForm.js,它不是一个屏幕,而是一个包含在访问代码屏幕中的组件。我尝试使用this.props.navigation.navigate('CreateAccountScreen');,但遇到错误“Undefined不是一个对象(评估'this.props.navigation')。经过一些试验和错误,我发现我只能在实际屏幕内使用react-navigation一些奇怪的原因。在此之后,我尝试使用this.statethis.setState({})to跟踪屏幕变量,并将其同步到实际的访问代码屏幕,所以我可以使用导航。不幸的是,this.setState还抛出“Undefined不是一个对象“错误。我在下面粘贴了我的代码的缩写版本。在屏幕文件问题之外实现此导航的最佳方法是什么?

App.js ---->

import { createStackNavigator, createAppContainer } from 'react-navigation';

import AccessScreen from './src/screens/AccessScreen';
import CreateAccountScreen from './src/screens/CreateAccountScreen';

const RootStack = createStackNavigator ({
    EnterAccessCode : {
        screen: AccessScreen
    },
    CreateAccount : {
        screen: CreateAccountScreen
    }
},
{
  headerMode: 'none'
});

const App = createAppContainer(RootStack);

export default App;

AccessForm.js ---->

import React from 'react';
import { StyleSheet, Text, View, TextInput, AlertIOS } from 'react-native';


var firebase = require("firebase");

if (!firebase.apps.length) { // Don't open more than one firebase session
  firebase.initializeApp({ // Initialize firebase connection
    apiKey: "key",
    authDomain: "domain",
    databaseURL: "url",
    storageBucket: "storage_bucket",
  });
}

this.codesRef = firebase.database().ref('codes'); // A reference to the codes section in the db

// this.state = {
//   screen: 0
// };

export default class LoginForm extends React.Component {
  constructor(props) {
    super(props);
    //this.checkCode = this.checkCode.bind(this); // throws error
  }
  render() {
    return (
      <View style={styles.container} >
        <TextInput
            style={styles.input}
            placeholder='Access Code'
            returnKeyType='go'
            onSubmitEditing={(text) => checkCode(text.nativeEvent.text)} // Checks the code entered
            autoCapitalize='none'
            autoCorrect={false}
        />
      </View>
    );
  }
}


function checkCode(text) {
  var code = text; // Set entered code to the var "code"
  var identifier = ""; // Used to store unique code object identifier
  codesRef.once('value', function(db_snapshot) {
    let codeIsFound = false
    db_snapshot.forEach(function(code_snapshot) { // Cycle through available codes in db
      if (code == code_snapshot.val().value) { // Compare code to db code
        codeIsFound = true;
        identifier = code_snapshot.key; // Code object ID
      }
    })
    if (codeIsFound) {
      deleteCode(identifier); // Delete the code if used, maybe do this after account is created?
      this.props.navigation.navigate('CreateAccountScreen');
      //this.setState({screen: 1}); // this throws error
      // MOVE TO NEXT SCREEN
      //this.props.navigation.navigate('AccountCreateScreen'); // throws error
    } else { // wrong code
      // note to self : add error message based on state var
      AlertIOS.alert("We're Sorry...", "The code you entered was not found in the database! Please contact Mr. Gibson for further assistance.");
    }
  });
}

function deleteCode(id) { // delete a code from unique ID
  firebase.database().ref('codes/' + id).remove();
}

// stylesheet is below

Login.js ---->

import React from 'react';
import { StyleSheet, Text, View, Image, TextInput, KeyboardAvoidingView, Platform } from 'react-native';
import AccessForm from './AccessForm';

export default class App extends React.Component {
  render() {
    return (
        <View>
            <View style={styles.logoContainer}>
                <Image 
                    source={require('../images/mhs.jpg')}
                    style={styles.logo}
                />
                <Text style={styles.app_title}>MHS-Protect</Text>
                <Text>An app to keep MHS safe and in-touch.</Text>
            </View>
            <KeyboardAvoidingView style={styles.container} behavior='padding'>
              <View style ={styles.formContainer}>
                  <AccessForm/>
              </View>
            </KeyboardAvoidingView>
        </View>
    );
  }
}

//styles below
javascript react-native react-navigation react-native-ios
2个回答
1
投票

import React from 'react';
import { StyleSheet, Text, View, TextInput, AlertIOS } from 'react-native';

var firebase = require('firebase');

if (!firebase.apps.length) {
  // Don't open more than one firebase session
  firebase.initializeApp({
    // Initialize firebase connection
    apiKey: 'key',
    authDomain: 'domain',
    databaseURL: 'url',
    storageBucket: 'storage_bucket',
  });
}

export default class LoginForm extends React.Component {
  constructor(props) {
    super(props);
    this.codesRef = firebase.database().ref('codes'); // A reference to the codes section in the db
  }

  checkCode = text => {
    var code = text; // Set entered code to the var "code"
    var identifier = ''; // Used to store unique code object identifier
    this.codesRef.once('value', function(db_snapshot) {
      let codeIsFound = false;
      db_snapshot.forEach(function(code_snapshot) {
        // Cycle through available codes in db
        if (code == code_snapshot.val().value) {
          // Compare code to db code
          codeIsFound = true;
          identifier = code_snapshot.key; // Code object ID
        }
      });
      if (codeIsFound) {
        this.deleteCode(identifier); // Delete the code if used, maybe do this after account is created?
        this.props.navigation.navigate('CreateAccount');
      } else {
        // wrong code
        // note to self : add error message based on state var
        AlertIOS.alert(
          "We're Sorry...",
          'The code you entered was not found in the database! Please contact Mr. Gibson for further assistance.'
        );
      }
    });
  };

  deleteCode = id => {
    firebase
      .database()
      .ref('codes/' + id)
      .remove();
  };

  render() {
    return (
      <View style={styles.container}>
        <TextInput
          style={styles.input}
          placeholder="Access Code"
          returnKeyType="go"
          onSubmitEditing={text => this.checkCode(text.nativeEvent.text)} // Checks the code entered
          autoCapitalize="none"
          autoCorrect={false}
        />
      </View>
    );
  }
}

1
投票

你的道具中应该有navigation对象。默认情况下,反应导航会将navigation传递给所有屏幕,但会传递其他组件。为此,您有两种选择: 1.将屏幕上的navigation道具传递给每个儿童组件(不推荐)。 2.使用withNavigation作为文件中的提及https://reactnavigation.org/docs/en/connecting-navigation-prop.html

import React from 'react';
import { Button } from 'react-native';
import { withNavigation } from 'react-navigation';

class MyBackButton extends React.Component {
  render() {
    return <Button title="Back" onPress={() => { this.props.navigation.goBack() }} />;
  }
}

// withNavigation returns a component that wraps MyBackButton and passes in the
// navigation prop
export default withNavigation(MyBackButton);

编辑:checkCode方法不属于您的LoginForm。你需要: 1.使其成为LoginForm的一部分。 2.记得使用bindarrow function定义。否则,您的this内部函数未定义。

import { withNavigation } from 'react-navigation';
class LoginForm extends React.Component {
    checkCode = (text) => {
        ....
    };
}
export default withNavigation(LoginForm);

你可以在这里阅读更多关于bind或箭头方法https://medium.com/shoutem/react-to-bind-or-not-to-bind-7bf58327e22a

© www.soinside.com 2019 - 2024. All rights reserved.