输入正确的代码后,我想使我的应用程序移至下一页,但是这样做一直很麻烦。我正在使用文件名AccessForm.js进行操作,该文件不是屏幕,而是访问代码屏幕中包含的组件。我尝试使用this.props.navigation.navigate('CreateAccountScreen');
,但遇到错误“未定义不是对象(评估'this.props.navigation')。经过反复试验,我发现我只能在内部使用react-navigation出于某种怪异的原因而创建了一个实际的屏幕。此后,我尝试使用this.state
和this.setState({})
来跟踪屏幕变量,并将其同步到实际的访问代码屏幕,以便我可以使用导航。不幸的是,this.setState
还会引发“未定义不是对象”错误。我在下面粘贴了我的代码的缩写版本。在屏幕文件问题之外实现这种导航的最佳方法是什么? / p>
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
答案 0 :(得分: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.请记住使用bind
或arrow function
定义。否则,未定义您的this
内部函数。
import { withNavigation } from 'react-navigation';
class LoginForm extends React.Component {
checkCode = (text) => {
....
};
}
export default withNavigation(LoginForm);
您可以在https://medium.com/shoutem/react-to-bind-or-not-to-bind-7bf58327e22a处了解有关bind
或箭头方法的更多信息
答案 1 :(得分: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>
);
}
}
答案 2 :(得分:0)
从以下位置复制并粘贴(参考):https://github.com/react-navigation/react-navigation/issues/1439#issuecomment-303661539
它对我有效。
您可以将顶级导航器引用传递给服务,并从该服务调度操作。
// App.js
import NavigatorService from './services/navigator';
const Navigator = StackNavigator({ /* ... */ })
class App extends Component {
// ...
render(): {
return (
<Navigator
ref={navigatorRef => {
NavigatorService.setContainer(navigatorRef);
}}
/>
);
}
}
// services/navigator.js
// @flow
import { NavigationActions } from 'react-navigation';
import type { NavigationParams, NavigationRoute } from 'react-navigation';
let _container; // eslint-disable-line
function setContainer(container: Object) {
_container = container;
}
function reset(routeName: string, params?: NavigationParams) {
_container.dispatch(
NavigationActions.reset({
index: 0,
actions: [
NavigationActions.navigate({
type: 'Navigation/NAVIGATE',
routeName,
params,
}),
],
}),
);
}
function navigate(routeName: string, params?: NavigationParams) {
_container.dispatch(
NavigationActions.navigate({
type: 'Navigation/NAVIGATE',
routeName,
params,
}),
);
}
function navigateDeep(actions: { routeName: string, params?: NavigationParams }[]) {
_container.dispatch(
actions.reduceRight(
(prevAction, action): any =>
NavigationActions.navigate({
type: 'Navigation/NAVIGATE',
routeName: action.routeName,
params: action.params,
action: prevAction,
}),
undefined,
),
);
}
function getCurrentRoute(): NavigationRoute | null {
if (!_container || !_container.state.nav) {
return null;
}
return _container.state.nav.routes[_container.state.nav.index] || null;
}
export default {
setContainer,
navigateDeep,
navigate,
reset,
getCurrentRoute,
};
然后您可以在任何地方使用Navigator服务。
赞:
import NavigatorService from './services/navigator';
NavigatorService.navigate('Home');