0
votes

I've spent 2 days search, reading and find lots of v3 and v4 class based examples for how to handle navigation in React Native Navigation.

All I want to achieve is to move between 2 of my screens using react native navigation. My App.js contains the Tab navigator and that works fine. The tab opens up a component (screen) called Mens and from there I want to be able to open up a PDP page that passes in properties of an article ID.

I have tried numerous ways of wiring up the application to allow this; I've read all the react native documentation and tried a number of approaches;

Created a seperate file to include the naviagtion stack;

import * as React from 'react'
import { NavigationContainer } from '@react-navigation/native'
import { createStackNavigator } from '@react-navigation/stack'
import News from './news';
import Mens from './mens'
import Watch from './watch'

const Stack = createStackNavigator()

function MainStackNavigator() {
  return (
    <NavigationContainer>
    <Stack.Navigator>
      <Stack.Screen name="News" component={News} />
      <Stack.Screen name="Mens" component={Mens} />
    </Stack.Navigator>
  </NavigationContainer>
  )
}

export default MainStackNavigator

But when I try to use one of the screens, I get an error. The onpress I try is;

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

I have also tried to move the NavigationContainer / Stack Navigator code into the News component, but I haven't manage to make that work.

The flow that I want is simple enough; App.js has my tabs, 5 tabs that navigate to the main screens and then on each of those, people can click on a list item in a flat list (which displays a summary) to read the full article.

The news.js file content is below;

import React, { useEffect, useState } from 'react';
import { ActivityIndicator, FlatList, Image, ListItem, Text, View, StyleSheet, ScrollView, TouchableOpacity, Alert} from 'react-native';
import Moment from 'moment';
import MatchReports from './matchreports.js';
import navigation from '@react-navigation/native';

const News = (props) => {
  const [isLoading, setLoading] = useState(true);
  const [data, setData] = useState([]);

  function chkValue(val) {
    if(val.length == 0){
       val = 'https://derbyfutsal.files.wordpress.com/2019/07/banner-600x300.png';
      }else{
        val = val;
   }
    return val;
  }
  useEffect(() => {
    fetch('https://xxxx')
      .then((response) => response.json())
      .then((json) => {
        setData(json)
        })
      .catch((error) => console.error(error))
      .finally(() => setLoading(false));
  }, []);

  return (

    <ScrollView>
      <View style={styles.body}>
        <Text style={styles.titlesnopadding}>Watch</Text>
        <View style={{height:200}}>
        <Watch />
        </View>
        <Text style={styles.titles}>Match reports</Text>
        <View style={{height:100}}>
        <MatchReports typeOfProfile='Men'/>
        </View>

      <Text style={styles.titles}>Latest News</Text>
      {isLoading ? <ActivityIndicator/> : (
        <FlatList
          data={data}
          keyExtractor={({ id }, index) => id}
          renderItem={({ item }) => (
          <View>
            <TouchableOpacity onPress={() => navigation.navigate('Mens')}>
            <Image style={styles.img} source={{ uri: chkValue(item.jetpack_featured_media_url) }} />
            <View>
                <Text style={styles.textbck}>{item.title.rendered.replace(/<\/?[^>]+(>|$)/g, "")}</Text>
                <Text style={styles.summary}>{item.excerpt.rendered.replace(/<\/?[^>]+(>|$)/g, "")}{"\n"}{Moment(item.date, "YYYYMMDD").fromNow()}</Text>
          </View>
          </TouchableOpacity>
          </View>
          )}
        />
      )}
    </View>
    </ScrollView>
  );
};

Any help is appreciated, as I've read so many using class instead of functional programming and out of date navigation that it's been challenging working it out.

EDIT:

I had missed the props.navigation.navigate('Mens'), which works fine now. Though its only half solves my problem.

I have the following inside my app.js;

import 'react-native-gesture-handler';
import React from 'react';
import { View, StyleSheet, Image } from 'react-native';
import News from './components/news';
import Shop from './components/shop';
import Mens from './components/mens';
import Fixtures from './components/fixtures';
import Ladies from './components/ladies';
import Pdp from './components/pdp'
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

const Tab = createBottomTabNavigator();

const App = () => {
return (
  <View style={styles.header}>
    <View>
    </View>
    <View style={styles.body}>
    <NavigationContainer>
      <Tab.Navigator>
         <Tab.Screen name="News" component={News} />
         <Tab.Screen name="Mens" component={Mens} />         
         <Tab.Screen
          name="icon"
          component={Shop}
          options={{
            title: '',
            tabBarIcon: ({size,focused,color}) => {
              return (
                <Image
                  style={{ marginTop:20,width: 80, height: 80 }}
                  source={{
                    uri:
                      'https://derbyfutsal.files.wordpress.com/2020/05/derby-futsal-logo-2019.png',
                  }}
                />
              );
            },
          }}
        />
         <Tab.Screen name="Ladies" component={Ladies} />
         <Tab.Screen name="Fixtures" component={Fixtures} />
       </Tab.Navigator>
       </NavigationContainer>
    </View>
  </View>
)
};

const styles = StyleSheet.create({
header: {
  marginTop: 20,
  height:0,
  flex: 1
},
body: {
  flex:2,
  flexGrow:2,
},
nav: {
fontSize: 20,
},
});

export default App;

Anything thats been set as tab Screen in this works just fine if I reference it in my news.js screen, but I don't want to declare PDP.js in this as I don't want it to display as a tab.

Instead once a user has gone to a screen using the tab navigation, the user then clicks on a item in the flatlist and it opens up pdp.js.

In many ways, once someone has opened up the main categories (as seen on the tab navigation) and clicked on an item in the flatlist, all I want to do is;

<a href="pdp.js?id=xxxxx">
1
What the error ? - Ardy Febriansyah
navigation.navigate('Mens') should be props.navigation.navigate('Mens'), whats the error that you are getting ? - Guruparan Giritharan
Thanks Guruparan, the missing part was props (which now thinking about it makes sense as my tab navigation is in my app.js). Though it's only half solved my problem; console.error: The action ‘NAVIGATE’ with payload {“name”:”Pip”} was not handled by any navigator. Do you have a screen named ‘Pdp’? This I think has happened as Mens is a component listed in the Tab Navigator, but pdp isn't (I don't want it on the main tab, but just as a stack navigation, so I guess I need to find a way to nest inside the app.js the stack navigation as well) - Carl Bruiners

1 Answers

1
votes

https://reactnavigation.org/docs/navigation-actions/#navigate

import { CommonActions } from '@react-navigation/native';

navigation.dispatch(
  CommonActions.navigate({
    name: 'Profile',
    params: {
      user: 'jane', // props.route.params.user
    },
  })
);