未定义不是对象('this.props.navigation.navigate')错误

时间:2020-07-20 02:36:09

标签: react-native

这是我的代码页,称为ProfileInfo:

import React from "react";
import { View, Text, StyleSheet, ActivityIndicator } from "react-native";
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from "react-native-responsive-screen";
import RegisterTextBox from "../../components/RegisterTextBox";
import AuthButton from "../../components/AuthButton";
import Avatar from "../../components/Avatar";
import firebase from "../../util/firebase";
import { setPhone, setIsProfileFilled } from "../../util/database";

export default class PersonalInfo extends React.Component {
  constructor(props) {
    super(props);
    this.updateUser = this.updateUser.bind(this);
    this.state = {
      displayName: "",
      phoneNumber: "",
      photoURL: "",
      buttonColor: "#8b898a",
      isLoading: false,
    };
  }

  updateInputVal = (val, prop) => {
    this.setState({ [prop]: val });
    this.changeColor();
  };

  changeColor() {
    let currentColor = this.state.buttonColor;
    if (this.state.displayName != "" && this.state.phoneNumber != "") {
      currentColor = "#7356bf";
    } else currentColor = "#8b898a";
    this.setState({ buttonColor: currentColor });
  }

  updateUser() {
    this.setState({ isLoading: true });
    var user = firebase.auth().currentUser;
    user
      .updateProfile({
        displayName: this.state.displayName,
        photoURL: this.state.photoURL,
        phoneNumber: setPhone(user.uid, this.state.phoneNumber),
      })
      .then(function () {
        // Update successful.
        console.log("Update Succed Moving to Update User Is Filled");
      })
      .then(() => {
        user.updateProfile({
          displayName: setIsProfileFilled(user.uid, true),
        });
        console.log("Update Succed Is Filled");
        this.setState({ isLoading: false });
      })
      .catch(function (error) {
        // An error happened.
        console.log(error);
        this.setState({ isLoading: false });
      });
    this.props.navigation.navigate("Waiting");
  }

  render() {
    const { navigation } = this.props;
    return (
      <View style={styles.container}>
        <View style={styles.titleContainer}>
          <Text style={styles.title}>Great! Let’s get to know YOU</Text>
        </View>
        <View style={styles.imageContainer}>
          <Avatar />
        </View>
        <View style={styles.inputContainer}>
          <RegisterTextBox
            type="name"
            style={styles.emailInput}
            placeholder="Your Name"
            value={this.state.displayName}
            onChangeText={(name) => {
              this.updateInputVal(name, "displayName");
            }}
          />
          <RegisterTextBox
            type="number"
            style={styles.emailInput}
            placeholder="Phone Number"
            value={this.state.phoneNumber}
            onChangeText={(number) =>
              this.updateInputVal(number, "phoneNumber")
            }
          />
        </View>
        <View style={styles.buttonContainer}>
          <AuthButton
            style={{ backgroundColor: this.state.buttonColor }}
            // CR: Use Disabled property instead of changing the style
            // disabled
            title="Continue"
            onPress={this.updateUser}
            text="Continue"
          ></AuthButton>
        </View>
      </View>
    );
  }
}
const styles = StyleSheet.create({
  //Containers
  container: {
    flex: 1,
  },
  titleContainer: {
    height: hp(10),
    width: wp(65.7),
    alignItems: "center",
    marginLeft: wp(17.4),
    marginRight: wp(17.4),
    marginTop: hp(12.7),
  },
  inputContainer: {
    marginTop: hp(6),
    width: wp(65.2),
    alignItems: "center",
    marginLeft: wp(17.4),
    marginRight: wp(17.4),
  },
  imageContainer: {
    marginTop: hp(7.3),
    alignItems: "center",

    height: hp(14.4),
    width: wp(100),
  },
  buttonContainer: {
    marginTop: hp(9),
    marginBottom: hp(14.1),
    alignItems: "center",
  },
  //Button
  loginButton: {
    flexDirection: "row",
    alignItems: "center",
    justifyContent: "center",
    borderRadius: 32.5,
    width: wp(78.3),
    height: hp(7.3),
    backgroundColor: "grey",
  },
  //Text
  title: {
    flex: 1,
    textAlign: "center",
    fontSize: hp(3.8),
  },
});

这是我的导航器:

import React from "react";
import { createStackNavigator } from "@react-navigation/stack";

//Screens
import Splash from "../screens/Auth/Splash";
import Login from "../screens/Auth/Login";
import Register from "../screens/Auth/Register";
import PersonalInfo from "../screens/Auth/PersonalInfo";
import Waiting from "../screens/Waiting";

const Stack = createStackNavigator();
export const AuthStack = () => {
  return (
    <Stack.Navigator initialRouteName="Splash">
      <Stack.Screen
        name="Splash"
        component={Splash}
        options={{ headerShown: false, headerTransparent: true }}
      />
      <Stack.Screen name="Login" component={Login} />
      <Stack.Screen
        name="Register"
        component={Register}
        options={{ headerTransparent: true, headerTitle: "" }}
      />
      <Stack.Screen
        name="PersonalInfo"
        component={PersonalInfo}
        options={{ headerTitle: "", headerTransparent: true }}
      />
      <Stack.Screen
        name="Waiting"
        component={Waiting}
        options={{ headerTitle: "", headerTransparent: true }}
      />
    </Stack.Navigator>
  );
};

我不明白为什么导航是未定义的,我正在尝试在updateuser完成后进行导航。 我也尝试navigation.navigate("Waiting");还是没有运气, 我不知道为什么无法识别我的导航器,其他页面只能在我遇到问题的页面上正常工作,也许我的功能有问题?

1 个答案:

答案 0 :(得分:2)

我创建了一个无需道具即可从任何地方导航的类。如果您愿意,可以使用我的课程。首先,您必须设置顶级导航。

在我的NavigationService.js中

import UIKit
import Foundation
import SwipeCellKit
import CoreData

//MARK: - Protocol to transfer the task Label to main VC:
protocol TaskDelegate {
    func updateTaskName(name:String)
}


//MARK: - Tasks View Controller:
class TasksViewController: UITableViewController, SwipeTableViewCellDelegate {
    
    


    let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext

    
    
    var tasksArray = [Task]()
    var delegate: TaskDelegate?
    
    var taskName = ""
    
    override func viewDidLoad(){
        super.viewDidLoad()
        loadTasks()
        
        
    }
    
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        navigationController?.navigationBar.prefersLargeTitles = true
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.prefersLargeTitles = false
    }
    
    
    

    // MARK: - Table view data source


    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return tasksArray.count
    }

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell") as! SwipeTableViewCell
        
        cell.delegate = self
        cell.textLabel?.text = tasksArray[indexPath.row].title
        cell.imageView?.image = UIImage(named: "icon-unchecked-checkbox.png")
        cell.detailTextLabel?.text = ""
        
        return cell
    }

    
    // MARK: - Table view delegate methods:
    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> [SwipeAction]? {
        guard orientation == .right else { return nil }

        
        let deleteAction = SwipeAction(style: .destructive , title: .none) { action, indexPath in
            // handle action by updating model with deletion
            
            self.context.delete(self.tasksArray[indexPath.row])
            self.tasksArray.remove(at: indexPath.row)
            
            
            self.delegate?.updateTaskName(name: "")
            self.saveTasks()
            
        }

        let infoAction = SwipeAction(style: .default, title: .none) { action, indexPath in return }
        
        deleteAction.transitionDelegate = ScaleTransition.default
//        deleteAction.transitionDelegate = ScaleTransition.init(duration: 0.50, initialScale: 0.50, threshold: 0.50)
        infoAction.transitionDelegate = ScaleTransition.default
        


        // customize the action appearance
        
        deleteAction.image = UIImage(named: "icon-trash")
        infoAction.image = UIImage(named: "icon-more")

        

        return [deleteAction, infoAction]
    }
    
    
    
    // method to customize the behavior of the swipe actions(the delete action):
    func tableView(_ tableView: UITableView, editActionsOptionsForRowAt indexPath: IndexPath, for orientation: SwipeActionsOrientation) -> SwipeOptions {
        var options = SwipeOptions()
        options.expansionStyle = .destructive
        options.transitionStyle = .drag
        options.buttonSpacing = 10
        options.expansionDelegate = ScaleAndAlphaExpansion.init(duration:  0.15, scale:  0.5, interButtonDelay:  0.30)


        return options
    }
    
    
    
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
       tableView.deselectRow(at: indexPath, animated: true)
        
        
        if tableView.cellForRow(at: indexPath)?.imageView?.image == UIImage(named: "icon-checked-checkbox.png") {
            let imageBox =  UIImage(named: "icon-unchecked-checkbox.png")

            tableView.cellForRow(at: indexPath)?.imageView?.image = imageBox
            
        } else {
            let imageBox = UIImage(named: "icon-checked-checkbox.png")
            tableView.cellForRow(at: indexPath)?.imageView?.image = imageBox
        }
    }
    
    
    
    
    // MARK: - Class Methods:
    //Adding task function:
    @IBAction func addPressedButton(_ sender: UIBarButtonItem) {
        var textField = UITextField()

        let alert = UIAlertController(title: "New Task", message: "Please insert a new task.", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))

        alert.addTextField(configurationHandler: { alertTextField in
            alertTextField.placeholder = "Please insert your task"
            textField = alertTextField
        })

        
        
        
        
        alert.addAction(UIAlertAction(title: "OK", style: .destructive, handler: { action in
            //We Add the task into our array of Task objects once we reach into here:
            
            
            let newTask = Task(context: self.context)
            newTask.title = textField.text
            
            
            
            self.taskName = newTask.title!
            self.delegate?.updateTaskName(name: self.taskName)
            
            
            self.tasksArray.append(newTask)
            self.saveTasks()
            
            
            self.tableView.reloadData()
        }))

        self.present(alert, animated: true)
    }

    
    func getDate() -> String{
        let dateFormatter : DateFormatter = DateFormatter()
        //  dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        dateFormatter.dateFormat = "yyyy-MMM-dd HH:mm:ss"
        let date = Date()
        let dateString = dateFormatter.string(from: date)
        let interval = date.timeIntervalSince1970
        
        return dateString
    }
    
}

如何使用?

import { NavigationActions } from 'react-navigation';

class NavigationService{
    _navigator = null;
    currentRoute = null;
    isNavigated = false;

    setTopLevelNavigator(navigatorRef) {
        _navigator = navigatorRef;
      }
      
    navigate(routeName, params) {
        _navigator.dispatch(
          NavigationActions.navigate({
            type: NavigationActions.NAVIGATE,
            routeName,
            params,
          })
        );
      }

      setCurrentRoute(routName){
        this.currentRoute = routName;
      }

      setNavigated(status){
        this.isNavigated = status;
      }
}




// add other navigation functions that you need and export them

const Navigation = new NavigationService();

export default Navigation;