Niloufar
Niloufar

Reputation: 532

Navigation.getParam is undefined while trying to pass function as parameter

I'm trying to use a function from my Main component in my details component which I user react navigation to navigate to and I want to save some changes in detail screen in my main component

//Main.js

import React from 'react';
import {
    StyleSheet ,
     Text,
     View, 
     TextInput,
     ScrollView,
     TouchableOpacity,
     KeyboardAvoidingView,
     AsyncStorage
    } from 'react-native'
import Note from './Note'
import { createStackNavigator, createAppContainer } from "react-navigation";
import Details from './Details';


export default class Main extends React.Component {

  static navigationOptions = {
    title: 'To do list',
    headerStyle: {
      backgroundColor: '#f4511e',
    },
  };

  constructor(props){
    super(props);
    this.state = {
      noteArray: [],
      noteText: ''
    };
  }
render() {

    let notes = this.state.noteArray.map((val,key) => {
      return <Note key={key} keyval={key} val={val}
      goToDetailPage= {() => this.goToNoteDetail(key)}
       />
    });
    const { navigation } = this.props;
    return(
        <View style={styles.container}>
         <ScrollView style={styles.scrollContainer}>
                {notes}
            </ScrollView>
           <Details saveEdit={this.saveEdit} />
        </View>

      );
    }
    goToNoteDetail=(key)=>{   
      this.props.navigation.navigate('DetailsScreen', {
        selectedTask: this.state.noteArray[key],
        saveEdit: this.saveEdit
      });
    }
     saveEdit = (editedTask,dueDate) => {
     this.state.noteArray.push({ 
    'creationDate': editedTask['creationDate'], 
    'taskName': editedTask['taskName'],
    'dueDate': dueDate
  });
  this.setState({noteArray:this.state.noteArray})
  this.saveUserTasks(this.state.noteArray) 
}    
      this.setState({noteArray:this.state.noteArray})
      this.saveUserTasks(this.state.noteArray) 
    }     
}

Then I try to use it as prop in my Detail.js

import React from 'react';
import {
    StyleSheet ,
     Text,
     View, 
     TextInput,
     Button,
     TouchableOpacity,

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

export default class Details extends React.Component {

   constructor(props){
    super(props);
   this.state = {
    dueDate = ''
   }
  }

  static navigationOptions = {
    headerStyle: {
      backgroundColor: '#f4511e',
    },  
  };

  componentDidMount = () => {
  this.getUserTasks()  
  } 
  render() {

    const { navigation } = this.props;
    const selectedTask = navigation.getParam('selectedTask', 'task');
    var { saveEdit} = this.props;

    return(
     <View key={this.props.keyval} style={styles.container}>
      <View style = { styles.info}>
              <Text style= {styles.labelStyle}> Due date:
              </Text>
              <TextInput
                        onChangeText={(dueData) => this.setState({dueData})}
                        style={styles.textInput}
                        placeholder= {selectedTask['dueDate']}  
                        placeholderTextColor='gray'
                        underlineColorAndroid = 'transparent'
                        >
              </TextInput>
      </View>
      <TouchableOpacity onPress={this.props.saveEdit(selectedTask, this.state.dueDate)} style={styles.saveButton}>
                <Text style={styles.saveButtonText}> save </Text>
      </TouchableOpacity>
    </View>
    );
  }
} 

I searched a lot to find the solution and I tried many of them but get different undefined errors. This is not what I did in the first place but when I search I found this solution here. And I know it causes lots of issues. I want to know how can I manage to access to main method from details and pass parameters to it or how can I manage to use main props in my details component

Upvotes: 1

Views: 13653

Answers (4)

Meo Flute
Meo Flute

Reputation: 1301

If you are using react-navigation 5, params is no longer under the navigation object but under route object. This is the link to the sample code: https://reactnavigation.org/docs/params

Upvotes: 6

Himmels DJ
Himmels DJ

Reputation: 445

There are many mistakes within your codes. First of all you are importing the navigation build-in function {createStackNavigator} in all your files, Main.js and Details.js :

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

That make me think that you didn't know how the stack navigation or navigation in general functions in react native. You should have a file that handles your routes configuration, let call it MyNavigation.js and then define the routes 'Main' and 'details' in MyNavigations,js. It's only inside MyNavigation.js that you can import "createStackNavigator". Then you will define your functions to move between the screens "Main" and "detail". Those functions will be passed as props to the routes when moving between one another. The overall action wihtin MyNavigation.js will look like:

import React from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import Main from './Main';
import Detail from './Detail';
const Stack = createStackNavigator();

function goToDetailFromMainScreen(){
     return(this.props.navigation.navigate('switch2'));
      }
function DetailSaves(){
     return(//your code here to save details);
      }

 //Here you pass the functions to Main Component to handele Detail componets 
   's actions

function switch1(){
  return(<Main GoToDetails={() => this.goTodetailFromMainScreen()} paramsForDetailActions={() => this.detailSaves()} />)
}

function switch2(){
  return(<Details />)
}

export default function MyNavigation() {
  return(
  <NavigationContainer>
    <Stack.Navigator initialRouteName='switch1'>
       <Stack.Screen name='switch1' options={{header:()=>null}} component={Main} />
       <Stack.Screen name='switch2' options={{headerTitle:"Detail"}} component={Detail} />
    </Stack.Navigator>
  </NavigationContainer>
)
}

Now inside Main.js you check the props functions passed to it from MyNavigation.js:

// Main.js

constructor(props){
    super(props);
  }

  goToDetails = () => {
    this.props.onPress?.();
  }
   paramsForDetailActions= () => {
    this.props.onPress?.();
  }

Upvotes: 0

DNA.h
DNA.h

Reputation: 863

I tried to run your code on my machine but it seems you have too many syntax error in your code (maybe because of copy pasta?)

but it seems you should change

<TouchableOpacity onPress={this.props.saveEdit(selectedTask, this.state.dueDate)}

in Detals.js to

<TouchableOpacity onPress={this.props.navigation.getParams('saveEdit')(selectedTask, this.state.dueDate)}

for clarification this worked for me in MainPage.js

    _test(){
      console.log('test');
    }
.
.

.
<ActionButton
     buttonColor="rgba(231,76,60,1)"
     onPress={() => NavigationService.navigate('AddNewSession', {test: this._test})}>
</ActionButton>

and in AddNewSession.js

  componentDidMount() 
    let test = this.props.navigation.getParam('test');
    test();
  }

Upvotes: 0

Jeff Gu Kang
Jeff Gu Kang

Reputation: 4869

Solution

<Details saveEdit={this.saveEdit} />

to

<Details navigation={this.props.navigation} saveEdit={this.saveEdit} />
render() {
    return(
        <View style={styles.container}>
         <ScrollView style={styles.scrollContainer}>
                {notes}
            </ScrollView>
           <Details navigation={this.props.navigation} saveEdit={this.saveEdit} />
        </View>

      );
}

Why?

You are using your Details component in Main screen. So you need to give navigation to Details's props from your Main to use navigation props in Details component.

Because your Details component is not the screen component registered in your navigator(router).

Upvotes: 0

Related Questions