NodeJS React-本机/ expo导航失败,出现"with Navigation“

92dk7w1h  于 2023-01-20  发布在  Node.js
关注(0)|答案(1)|浏览(148)

我正在制作一个安卓应用程序,最近添加了on-Boarding屏幕,所以我编辑了我的app.js(包含导航器),使它更完美。在添加on-Boarding屏幕之前,我可以使用'this.props.navigation. navigation(' Main ')从登录页面导航到主页。现在,我不能再这样做了。所以我尝试使用'react-navigation'中的'withNavigation':我用这个HOC Package 了我的Login类,但是得到了这个错误:
Invariant Violation: withNavigation can only be used on a view hierarchy of a navigator. The wrapped component is unable to get access to navigation from props or context.
我敢打赌我的组件被 Package 在一个导航器中:/
下面是我的App.js

import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import React, { useState, useEffect } from 'react';
import {DEFAULT} from "./.app/public/themes/variables"
import AsyncStorage from '@react-native-async-storage/async-storage'; // -> necessaire pour le onboarding

import * as NavigationBar from 'expo-navigation-bar';
import * as StatusBar from 'expo-status-bar';

import Login from "./.app/public/auth/login.js" //devlogin
import BottomNav from "./.app/public/navigator/navbar.js"
import LoginWithoutFastCo from "./.app/public/auth/loginwofc.js"
import OnboardingScreen1 from './.app/public/components/onboarding/1.js';
import { NavigationContainer } from '@react-navigation/native';

const AppNavigator = createStackNavigator(
  {
    // Test: Test,
    Login: Login,
    Main: BottomNav,
    Reload: LoginWithoutFastCo,
    Onboarding1: OnboardingScreen1,
  },
  {
    headerMode: "none",
    initialRouteName: 'Onboarding1',
  },
  NavigationBar.setBackgroundColorAsync("black"),
  NavigationBar.setButtonStyleAsync("light")
);

const AppContainer = createAppContainer(AppNavigator);

export default function App() {
  const [showOnboarding, setShowOnboarding] = useState(true);

  useEffect(() => {
    // check if onboarding has been shown before
    // you can use AsyncStorage or any other method to persist the state
    const checkOnboardingShown = async () => {
      const hasShownOnboarding = await AsyncStorage.getItem('hasShownOnboarding');
      if (hasShownOnboarding) {
        setShowOnboarding(false);
      } else {
        await AsyncStorage.setItem('hasShownOnboarding', 'true');
      }
    };

    checkOnboardingShown();
  }, []);

  if (showOnboarding) {
    return (
      <NavigationContainer independent={true}>
        <AppContainer />
      </NavigationContainer>
    );
  } else {
    return (
      <NavigationContainer independent={true}>
        <Login /> //HERE'S CALLED MY COMPONENT
      </NavigationContainer> //AND HERE'S THE WRAP (I SUPPOSE)
     );
  }
}

下面是我的login类组件:

//import modules
import {imports} from '../../private/imports.js';
import React, { useState } from 'react';
import { ToastAndroid, Text, View, TextInput, TouchableOpacity, Image, KeyboardAvoidingView, Pressable, Keyboard } from "react-native";
import { Ionicons } from '@expo/vector-icons'
import * as NavigationBar from 'expo-navigation-bar';
import { encrypt, decrypt } from "../util/crypto";
import AsyncStorage from '@react-native-async-storage/async-storage';

import { withNavigation } from 'react-navigation';

import {defaultCSS} from "../stylesheets/_default/login"; //default theme

//import assets/utils
const logo = require('../assets/images/logoRond.png')
let dataReady = false;

class Login extends React.Component {

  // Définition de la fonction errorMessage qui renvoie un message d'erreur sur android ou sur iOS
  errorMessage = (err) => {
    if (Platform.OS === 'android') { // Si l'OS est android
      ToastAndroid.show(err, ToastAndroid.SHORT) // Affiche un message d'erreur sur android
    } else if (Platform.OS === "ios") { // Sinon si l'OS est iOS
      AlertIOS.alert(err); // Affiche une alerte sur iOS
    } else {
      alert(err); // Sinon affiche une alerte
    }
  }

  state = {
    keptName: "",
    keptPassword: "",
    disabledButton: false,
  }

  //verification des données
  continue = async ({ navigation }) => {
    this.setState({ disabledButton: true})

    if ( this.state.name == "" || this.state.pwd == "" || this.state.name == undefined || this.state.pwd == undefined) { 
      if (await AsyncStorage.getItem("username") != "" || await AsyncStorage.getItem("username") != undefined || await AsyncStorage.getItem("password") != "" || await AsyncStorage.getItem("password")!= undefined) {
        this.state.name = decrypt(await AsyncStorage.getItem("username"));
        this.state.pwd = decrypt(await AsyncStorage.getItem("password"));
      }
      else return this.errorMessage("Merci de remplir tout les champs de connexion :)") 
    }
    let userN = this.state.name;
    userN = userN.slice(0, userN.indexOf('.'));
    console.log('\x1b[36m%s\x1b[0m', `>> connexion de ${userN}`);
    this.errorMessage(`Bonjour, ${userN}`);

    const username = encrypt(this.state.name); // On encrypte le nom d'utilisateur
    const password = encrypt(this.state.pwd); // On encrypte le mot de passe
    //console.log(username, password)
    
    const franck =  Object(JSON.parse(await AsyncStorage.getItem("franck")))
    const sessionDate = new Date(franck.session).getDay()
    const todayDate = new Date().getDay()

    
     if( sessionDate == todayDate && decrypt(username) == decrypt(await AsyncStorage.getItem("username")) && decrypt(password) == decrypt(await AsyncStorage.getItem("password"))) {
       await AsyncStorage.setItem("franck", JSON.stringify(franck));
       navigation.navigate('Main') // On navigue vers la page principale
       //console.log(await AsyncStorage.getItem("franck")); 
       console.log("Fast connection");
     } else {
      try {
        const response = await fetch(`link-to-the-api`); // On récupère les données de pronote
        const franck = await response.json(); // On récupère les données de pronote
        await AsyncStorage.setItem("franck", JSON.stringify(franck));

        await AsyncStorage.setItem("username", username);
        await AsyncStorage.setItem("password", password);

        //console.log(await AsyncStorage.getItem("franck")); 
        navigation.navigate('Main'); // On navigue vers la page principale
        console.log("Slow connection");
      } catch {
        this.setState({ disabledButton: false })
        return this.errorMessage("Identifiant ou Mot de passe incorrect !"); // Si l'identifiant ou le mot de passe est incorrect, on affiche un message d'erreur
      }
    }
    
  }

  getID = async () => {
    if ( dataReady == false ){
      try {
        const keptName = decrypt(await AsyncStorage.getItem("username"));
        const keptPassword = decrypt(await AsyncStorage.getItem("password"));
        console.log( "Existing user: "+ keptName)
        this.setState({ keptName: keptName });
        this.setState({ keptPassword: keptPassword });
        dataReady = true;

      } catch {
        const keptName = "";
        const keptPassword = "";
        console.log( "No existing user: "+ keptName)
        this.setState({ keptName: keptName });
        this.setState({ keptPassword: keptPassword });
        dataReady = true;
      }
      
    }
  }

  //keyboard listeners
  UNSAFE_componentWillMount() {
    this.keyboardDidShowListener = Keyboard.addListener('keyboardDidShow', this._keyboardDidShow);
    this.keyboardDidHideListener = Keyboard.addListener('keyboardDidHide', this._keyboardDidHide);
  }

  UNSAFE_componentWillUnmount() {
    this.keyboardDidShowListener.remove();
    this.keyboardDidHideListener.remove();
  }

  // _keyboardDidShow () {
  //   alert('Keyboard Shown');
  // }

  _keyboardDidHide() {
    NavigationBar.setVisibilityAsync("hidden");
    NavigationBar.setBehaviorAsync('overlay-swipe');
    NavigationBar.setButtonStyleAsync("light");
  }

  render() {
    this.getID()

    //checkbox 'se souvenir de moi'
    function CheckBox() {
      const [checked, onChange] = useState(false);

      function onCheckmarkPress() {
        onChange(!checked);
      }

      return (
        <Pressable
          style={[defaultCSS.checkboxBase, checked && defaultCSS.checkboxChecked]}
          onPress={onCheckmarkPress}>
          {checked && <Ionicons style={defaultCSS.check} name="checkmark" size={24} color="white" />}
        </Pressable>
      );
    }
    //checkbox 'Connexion rapide'
    function CheckBox2() {
      const [checked2, onChange2] = useState(false);

      function onCheckmarkPress2() {
        onChange2(!checked2);
      }

      return (
        <Pressable
          style={[defaultCSS.checkboxBase, checked2 && defaultCSS.checkboxChecked]}
          onPress={onCheckmarkPress2}>
          {checked2 && <Ionicons style={defaultCSS.check} name="checkmark" size={24} color="white" />}
        </Pressable>
      );
    }

    if (dataReady)  {
      return (
        <>
        <KeyboardAvoidingView behavior={Platform.OS === "ios" ? "padding" : "height"}
          enabled={true} style={defaultCSS.container} >
          <View style={defaultCSS.container}>
            <View style={defaultCSS.circle} />
                   

            <View style={{ marginTop: 64 }}>
              <Image source={logo}
                style={{ width: 100, height: 100, alignSelf: "center" }} />
            </View>

            <View style={{ marginHorizontal: 32 }}>
              <Text style={defaultCSS.header}>Bonjour, </Text>
              <Text style={defaultCSS.underHeader}>connectez-vous pour acceder à nos services</Text>

              <TextInput defaultValue={this.state.keptName}
                         autoComplete="username"
                         style={defaultCSS.textInput}
                         placeholder="Nom d'utilisateur atrium"
                         placeholderTextColor={'#80786a'}
                onChangeText={name => {
                  this.setState({ name })
                }}
                value={this.state.name}
              />

              <TextInput defaultValue={this.state.keptPassword}
                         autoComplete="password"
                         secureTextEntry={true}
                         style={defaultCSS.textInput}
                         placeholder="Mot de passe atrium"
                         placeholderTextColor={'#80786a'}
                onChangeText={pwd => {
                  this.setState({ pwd })
                }}
                value={this.state.pwd}
              />

              {/* <CheckBox />
              <Text style={defaultCSS.checkboxLabel}>Se souvenir de moi</Text>
              <CheckBox2 />
              <Text style={defaultCSS.checkboxLabel}>Connexion rapide</Text> */}



              <View style={{ alignItems: "flex-end", marginTop: 64 }}>
                <TouchableOpacity disabled={this.state.disabledButton}
                                  activeOpacity={0.6}
                                  style={!this.state.disabledButton ? defaultCSS.continue : defaultCSS.continueDisabled}
                                  onPress={this.continue}>
                  <Ionicons name="arrow-forward-outline" size={24} color='#FFF' />
                </TouchableOpacity>
              </View>
            </View>

            <View style={defaultCSS.bottomContainer}>
              <View style={defaultCSS.bottomBox}>
                <Text style={defaultCSS.basicText}>Si vous avez oublié vos identifiants,
                 rien de grave, réinitialisez-les directement via Atrium!</Text>
              </View>
              <View style={defaultCSS.bottomBox}>
                <Text style={defaultCSS.basicText}>
                  JDO-Copilot ne garde pas de données personnelles.</Text>
              </View>
            </View>
          </View>

        </KeyboardAvoidingView>
        </>
      );
    } else {
      return(
        <View style={{backgroundColor: '#555555'}}>
        </View>
      );
    }
  }
}

export default withNavigation(Login);

我希望你能帮助我,谢谢你,我为我糟糕的英语道歉:)

o4hqfura

o4hqfura1#

可以使用“ref”属性设置对特定导航容器的引用,然后使用该引用导航到不同屏幕,而无需使用“navigation”属性。要了解有关此方法的详细信息,可以查看React Navigation https://reactnavigation.org/docs/navigating-without-navigation-prop/上的文档

相关问题