Home > Mobile >  React Native - Navigation.navigate() only works within an onPress function
React Native - Navigation.navigate() only works within an onPress function

Time:05-03

In my app,

onPress={() => navigation.navigate('<ScreenName>')} 

works flawlessly, while if I try to change the screen within a function called when I tap a button, for example

const signup = (mobileNumber, {navigation}) => {
Object.keys(mobileNumber).forEach((key) => {
    console.log(mobileNumber[key]);
});

if (mobileNumber.mobileNumber == null) {
    Alert.alert("Oops!", "Please insert your mobile number.");
    return;
}

let dataToSend = {mobile_number: mobileNumber.mobileNumber};
let formBody = [];
for (let key in dataToSend) {
    let encodedKey = encodeURIComponent(key);
    let encodedValue = encodeURIComponent(dataToSend[key]);
    formBody.push(encodedKey   '='   encodedValue);
}
formBody = formBody.join('&');

fetch('https://mywebsite.com/api/v1/createAccount.php', {
    method: 'POST',
    body: formBody,
    headers: {
    //Header Defination
    'Content-Type':
    'application/x-www-form-urlencoded;charset=UTF-8',
    },
})
.then((response) => response.json())
.then((responseJson) => {
console.log(responseJson);
// If server response message same as Data Matched
if (responseJson.status === 'success') {
    //Alert.alert("Excellent!", "Please go on");
    navigation.navigate('<ScreenName>');
} else {
    console.log('Please check your mobileNumber');
}
})
.catch((error) => {
//Hide Loader
console.error(error);
});
}


function JoinScreen({ navigation }) {
const [mobileNumber, setMobileNumber] = useState(null);
const [isLoading, setLoading] = useState(true);

const [data, newData] = useState(null);

useEffect(() => {
    fetch("https://mywebsite.com/api/v1/createAccount.php")
        .then((response) => response.text())
        .then((response) => newData(response));
}, []);

return (
    <>
        <StatusBar hidden />
        <SafeAreaView style={{ flex: 1, alignItems: 'center', backgroundColor: '#262423' }}>

            <TextInput
                style={styles.input}
                placeholder="Your mobile number"
                placeholderTextColor="#fff"
                autoCapitalize="none"
                autoCorrect={false}
                onChangeText={(val) => setMobileNumber(val)}
                keyboardType="phone-pad"
            />

            <TouchableOpacity onPress={() => signup({ mobileNumber })}>
                <Text style={{ textAlign: "center", paddingTop: 20, color: "#babf26", fontSize: 20 }} >Create account</Text>
            </TouchableOpacity>
        </SafeAreaView>
    </>
);

}

The app returns "TypeError: undefined is not an object (evaluating '_ref6.navigation')"

If can be helpful, if in the "signup" function I don't wrap "navigation" within curly brackets, I get "undefined is not an object (evaluating 'navigation.navigate')"

CodePudding user response:

You do not pass the navigation object to the signup function. The statement

const signup = (mobileNumber, {navigation})

is not valid. The curly braces are used for destructuring properties from an object that is passed to a function. The reason why JoinScreen({ navigation }) works is (most likely) because JoinScreen is defined as a screen inside a navigator. Thus, the navigation framework does pass an object to all the screens that are defined as a screen in a navigator, and part of this object is the navigation object which you can destructure using curly braces.

For signup this is not the case, since this is just a function. However, you can just pass it from JoinScreen as follows.

function JoinScreen({ navigation }) {
 ...
  <TouchableOpacity onPress={() => signup(mobileNumber, navigation)}>
                <Text style={{ textAlign: "center", paddingTop: 20, color: "#babf26", fontSize: 20 }} >Create account</Text>
            </TouchableOpacity>
}

Then, your signup function.

const signup = (mobileNumber, navigation) => {

...

}

CodePudding user response:

Your signup function should either be inside of your screen component, or you should pass the navigation object as an argument.

  • Related