简体   繁体   English

react native - 将导航道具从父级传递给子级

[英]react native - Passing navigation props from parent to child

I'm trying to create a simple-ish mobile app, but I'm pretty new to this.我正在尝试创建一个简单的移动应用程序,但我对此很陌生。 I've spent some time searching about the errors I'm getting.我花了一些时间搜索我遇到的错误。 It seems like a common problem, but they all had the same/similar solutions but the solutions didn't work for me.这似乎是一个常见问题,但他们都有相同/相似的解决方案,但这些解决方案对我不起作用。

What is I'm trying to do?我想做什么? Right now the app is two pages, the home screen (Overview Cards) and the Add Card screen.现在该应用程序有两个页面,主屏幕(概览卡)和添加卡屏幕。

  1. There's a button on the Overview Cards that takes you to Add Card.概览卡上有一个按钮,可将您带到添加卡。
  2. Add Card allows you to fill out some TextInput boxes and Add Card 允许您填写一些 TextInput 框和
  3. Add Card should allow you to press the save button and be taken back to the Overview Card screen and see the data you entered in the form.添加卡应该允许您按下保存按钮并返回到概览卡屏幕并查看您在表单中输入的数据。

However, I am getting stuck at Step 3. I am trying to make the Save button navigate the user back to Overview Cards, but there are simply errors instead.但是,我被困在第 3 步。我试图让“保存”按钮将用户导航回概览卡,但只是出现了错误。

Below is my code, the errors I'm getting, and then what I've tried.下面是我的代码,我得到的错误,然后是我尝试过的。

App.js应用程序.js

import React from 'react';
import { StyleSheet, Text, TextInput, View, Button, TouchableOpacity, ShadowPropTypesIOS } from 'react-native';
import AddCard from './components/AddCard.js';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { useNavigation } from '@react-navigation/native';

function HomeScreen({ navigation }) {
  return (
    <View style={styles.homeContainer}>
      <Button title="Add Card" onPress={() => navigation.navigate('Add Card')}/>
      {/* <Text value={this.props.inputValFT}/> */}
      <Text style={styles.textStyle} >VISA xxxx</Text>
      <Text style={styles.textStyle}>MASTERCARD xxxx</Text>
      <Text style={styles.textStyle}>AMEX xxxx</Text>
    </View>
  );
}

function AddCardScreen() {
  return (
    <View style={styles.addCardContainer}>
      <AddCard navigation={this.props.navigation} /> // **HERE**
    </View>
  );
}

const Stack = createStackNavigator();

function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Overview Cards' }} />
        <Stack.Screen name="Add Card" component={AddCardScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
}
// function AddCardButton(){
//       return (
//           <View style={styles.buttonContainer}>
//               <TouchableOpacity>
//                   <Text style={styles.button}>Add Card</Text>
//               </TouchableOpacity>
//           </View>
//       );
//   }

export default App;

const styles = StyleSheet.create({
  homeContainer: {
    flex: 1,
    backgroundColor: '#ef95b1',
    alignItems: 'center',
    justifyContent: 'flex-start',
  },
  addCardContainer: {
    flex: 1,
    backgroundColor: '#28cdf0',
    justifyContent: 'flex-start',
  },
  buttonContainer: {
    flexDirection: 'row',
    alignSelf: 'flex-end',
    marginTop: 15,
  },
  button: {
    flexDirection: 'row',
    alignSelf: 'flex-end',
    marginTop: 15,
    right: 10,
    backgroundColor: '#2565ae',
    borderWidth: 1,
    borderRadius: 12,
    color: 'white',
    fontSize: 15,
    fontWeight: 'bold',
    overflow: 'hidden',
    padding: 10,
    textAlign:'center',
  },
  textStyle: {
    padding: 10,
  }
});

Navigation.js导航.js

import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { createAppContainer } from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
import AddCardScreen from './AddCard';

  const RootStack = createStackNavigator(
    {
      Home: HomeScreen,
      AddCard: AddCardScreen,
    },
    {
      initialRouteName: 'Home',
    }
  );

  const AppContainer = createAppContainer(RootStack);

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: '#ef95b1',
      alignItems: 'center',
      justifyContent: 'flex-start',
    },
    textStyle: {
      padding: 10,
    }
  });

  export default createAppContainer(Navigation);

AddCard.js AddCard.js

import React, { Component } from 'react';
import { StyleSheet, View, Text, TextInput, TouchableOpacity } from 'react-native';
import { Input } from 'react-native-elements'
import { ScrollView } from 'react-native-gesture-handler';

// import { loadSettings, saveSettings } from '../storage/settingsStorage';

class AddCardScreen extends Component {
   constructor(props) {
    super(props);
    this.state = {
        firstTwo  : '',
        lastFour  : '',
        recentAmt : ''
    };

    this.addFT = this.addFT.bind(this)
    this.addLF = this.addLF.bind(this)
    this.addRecAmt = this.addRecAmt.bind(this)
   }

   static navigationOptions = {
       title: 'Add Card'
    };

   addFT(firstTwo) {
    this.setState(Object.assign({}, this.state.firstTwo, { firstTwo }));
  }

  addLF(lastFour) {
    this.setState(Object.assign({}, this.state.lastFour, { lastFour }));
  }

  addRecAmt(recentAmt) {
    this.setState(Object.assign({}, this.state.recentAmt, { recentAmt }));
  }

  // handleSubmit() {
  //  alert('New card saved. Returning to Home to view addition.');
  //  navigation.navigate('Home')
  // } // firstTwo, lastFour, recentAmt

    render() {
        const {navigation} = this.props;
        return (
            <ScrollView>
                <View style={styles.inputContainer}>
                    <Text h1> "Add a new card!" </Text> 
                    <TextInput 
                    style={styles.textInput}
                    placeholder="First two digits of card"
                    placeholderTextColor="#000000"
                    keyboardType={'number-pad'}
                    maxLength = {2}

                    onChangeText={this.addFT}
                    inputValFT={this.state.firstTwo}
                    />
                    <TextInput
                    style={styles.textInput}
                    placeholder="Last four digits of card"
                    placeholderTextColor="#000000"
                    keyboardType={'number-pad'}
                    maxLength = {4}

                    onChangeText={this.addLF}
                    inputValLF={this.state.lastFour}
                    />
                    <TextInput
                    style={styles.textInput}
                    placeholder="Most recent dollar amount"
                    placeholderTextColor="#000000"
                    keyboardType={'decimal-pad'}

                    onChangeText={this.addRecAmt}
                    inputValRA={this.state.recentAmt}
                    />
                </View>
                <View style={styles.inputContainer}>
                    <TouchableOpacity 
                    style={styles.saveButton}
                    onPress={() => navigation.navigate('Home')}> // ** HERE 2 **
                        <Text style={styles.saveButtonText}>Save</Text>
                    </TouchableOpacity>
                </View>
            </ScrollView>
        );
    }
}
// this.handleSubmit.bind(this)
export default AddCardScreen;

const styles = StyleSheet.create({
    inputContainer: {
        paddingTop: 15
      },
      textInput: {
        borderColor: '#FFFFFF',
        textAlign: 'center',
        borderTopWidth: 1,
        borderBottomWidth: 1,
        height: 50,
        fontSize: 17,
        paddingLeft: 20,
        paddingRight: 20
      },
      saveButton: {
        borderWidth: 1,
        borderColor: '#007BFF',
        backgroundColor: '#007BFF',
        padding: 15,
        margin: 5
      },
      saveButtonText: {
        color: '#FFFFFF',
        fontSize: 20,
        textAlign: 'center'
      }

});

The errors I'm getting:我得到的错误:

In App.js you can see the ** HERE ** that I put in. When I try to run this, the app loads fine until I click the "Add Card" button.在 App.js 中,您可以看到我输入的 ** HERE **。当我尝试运行它时,应用程序加载正常,直到我单击“添加卡”按钮。 I get this error: undefined is not an object (evaluating 'this.props.navigation') .我收到此错误: undefined is not an object (evaluating 'this.props.navigation')

If I take the navigate={this.props.navigation} part out from App.js, the app loads as it's meant to again, but this time I can click the "Add Card" button and reach the next screen with no issue.如果我从 App.js 中取出navigate={this.props.navigation}部分,应用程序会再次按预期加载,但这次我可以单击“添加卡”按钮并毫无问题地进入下一个屏幕。 I fill out the form (TextInput parts in AddCard.js), but when I click the "Save" button, the app crashes.我填写了表单(AddCard.js 中的 TextInput 部分),但是当我单击“保存”按钮时,应用程序崩溃了。 The error is: TypeError: undefined is not an object (evaluating 'navigation.navigate') .错误是: TypeError: undefined is not an object (evaluating 'navigation.navigate') Most likely because of what I'm doing with onPress where it says ** HERE 2 ** in AddCard.js.很可能是因为我在 onPress 上所做的事情,它在 AddCard.js 中显示 ** HERE 2 **。 handleSubmit() is currently commented out, but it used to be inside the onPress. handleSubmit() 目前已被注释掉,但它曾经在 onPress 内部。

What I've tried:我试过的:

Some of the answers I saw were that I need to pass in navigation from the parent to the child and that will make it work.我看到的一些答案是我需要将导航从父级传递给子级,这将使它起作用。 By trying that, I get the errors I mentioned earlier.通过尝试,我得到了我之前提到的错误。 I also saw that someone mentioned using "withNavigation" or "useNavigation" which was supposed to allow the child to access navigation, but that didn't work for me either.我还看到有人提到使用“withNavigation”或“useNavigation”应该允许孩子访问导航,但这对我也不起作用。 Below are some of the links that I was trying to follow.以下是我尝试关注的一些链接。

How do I pass navigation props from parent component to header? 如何将导航道具从父组件传递到 header?

Pass navigation.navigate to Child Component 将 navigation.navigate 传递给子组件

https://reactnavigation.org/docs/use-navigation/ https://reactnavigation.org/docs/use-navigation/

Thank you for reading, hopefully my explanation is clear enough.感谢您的阅读,希望我的解释足够清楚。

I think your problem is somewhere here:我认为您的问题出在此处:

function AddCardScreen({ navigation }) {
  return (
    <View style={styles.addCardContainer}>
      <AddCard navigation={navigation} />
    </View>
  );
}
  • There is no this , you're not in a class component, therefore this doesn't exists没有this ,你不在 class 组件中,因此this不存在
  • The prop you are trying to pass should be called navigation and not navigate , since that's how you try to access it in the child component.您尝试传递的道具应该称为navigation而不是navigate ,因为这就是您尝试在子组件中访问它的方式。
  • The navigation prop needs to be destructured inside the function argument function AddCardScreen({ navigation }) , same as you already do for HomeScreen . navigation道具需要在 function 参数function AddCardScreen({ navigation })中进行解构,就像您已经为HomeScreen所做的一样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM