通过导航道具传递到外部组件

时间:2020-05-06 09:55:44

标签: react-native react-navigation

我正在尝试从组件内部导航,但无法终生解决。

这是我的App.tsx代码:

import * as React from 'react';
import { Image, ScrollView, RefreshControl, Text} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';

import { DashboardView } from './views/Dashboard';
import { MessagesView } from './views/Messages';
import { WisdomReplays } from './views/WisdomReplays';
import { TodoView } from './views/Todo';
import { MoreOptionsView } from './views/MoreOptions';
import { AuthView } from './views/Auth';

import { Header, ListItem, Icon, ThemeProvider } from 'react-native-elements';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import Ionicons from 'react-native-vector-icons/Ionicons';

import config from './core/Config.json';

function DashboardScreen() {
  return (
  <ScrollView>
    <DashboardView/>
  </ScrollView>
  );
}

function MessagesScreen() {
  return (
  <ScrollView>
    <MessagesView/>
  </ScrollView>
  );
}

function TodoScreen() {
  return (
  <ScrollView>
    <TodoView/>
  </ScrollView>
  );
}

function SocialScreen({ navigation }) {
  return (
    <>
    <Text onPress={() => navigation.navigate('Todo')}> Test </Text>
    <WisdomReplays/>
    </>
  );
}

function MoreOptionsScreen() {
  return (
    <MoreOptionsView/>
  );
}

const Tab = createBottomTabNavigator();

export default function App() {

  if (config.access_token != null) {

    return (
      <NavigationContainer>
        <ThemeProvider>
          <Header
            statusBarProps={{ barStyle: 'light-content' }}
            barStyle="light-content"
            centerComponent={<Image style={{ height: 35 }} source={require('./images/bms_logo_light.png')}
            resizeMode="contain"/>}
            containerStyle={{
              backgroundColor: '#343434',
              justifyContent: 'space-around',
              borderBottomColor: "#323232",
            }}
          />
        </ThemeProvider>
        <Tab.Navigator
          screenOptions={({ route }) => ({
            tabBarIcon: ({ focused, color, size }) => {
              let iconName;

              if (route.name === 'Home') {
                iconName = focused
                  ? 'ios-home'
                  : 'ios-home';
              } else if (route.name === 'Messages') {
                iconName = focused ? 'ios-paper-plane' : 'ios-paper-plane';
              } else if (route.name === 'Todo') {
                iconName = focused ? 'ios-list-box' : 'ios-list';
              } else if (route.name === 'More') {
                iconName = focused ? 'ios-more' : 'ios-more';
              } else if (route.name === 'Videos') {
                iconName = focused ? 'ios-videocam' : 'ios-videocam';
              }
              // You can return any component that you like here!
              return <Ionicons name={iconName} size={size} color={color} />;
            },
          })}
          tabBarOptions={{
            activeTintColor: '#ffcc07',
            inactiveTintColor: 'gray',
          }}
        >
          <Tab.Screen name="Home" component={DashboardScreen} />
          <Tab.Screen name="Messages" component={MessagesScreen} />
          <Tab.Screen name="Todo" component={TodoScreen} />
          <Tab.Screen name="Videos" component={SocialScreen} />
          <Tab.Screen name="More" component={MoreOptionsScreen} />
        </Tab.Navigator>
      </NavigationContainer>
    );

  } else {

    return (
      <AuthView/>
    );

  }

}

在上面的测试中,导航效果完美。

我想做到这一点,以便可以从 WisdomReplays 组件内部运行navigation.navigate('Todo')} WisdomReplays 如下:

import React, { Component } from 'react'
import { StyleSheet, Image, ActivityIndicator, FlatList, TouchableOpacity, View, Text, RefreshControl } from 'react-native';
import { Title, Paragraph, Card } from 'react-native-paper';
import { Icon } from 'react-native-elements';
import config from '../core/Config.json';

const LeftContent = props => <Image style={{ width: 45, height: 45, borderRadius: 45 / 2 }} {...props} source={require('../images/rik-icon.jpg')} resizeMode="contain"/>

const LeftContentSocialHeader = props => <Icon name='ios-videocam' type='ionicon' size="43" color="#ffcc07" />

const styles = StyleSheet.create({
  contentItem: {
    marginTop: 20,
    marginHorizontal: 15,
    borderRadius: 10,
  }, 
  socialCardPost: {
    marginBottom: 10,
    borderRadius: 0
  },
  CardHeader: {
    marginBottom: 10,
    borderRadius: 0
  },
  Loader: {
    marginTop: 250,
  },
  container: {
    flex: 1,
  },
  player: {
    flex: 1,
  },
});

export class WisdomReplays extends Component {

    constructor(props){
      super(props);
      this.state = {
        videoList: [],
        loading: true,
        page: 1,
        isFetching: false
      }
    }

    async componentDidMount() {
      this.fetchRecords('1');
    }

    onRefresh() {
      this.setState({ isFetching: true }, function() { this.refreshRecords() });
    }

    onScrollHandler = () => {
      this.setState({
         page: this.state.page + 1
      }, () => {
         this.fetchRecords(this.state.page);
      });
    }

    fetchRecords = (page) => {
      fetch('http://######/api/replays/index.php?page='+page+'&ac='+config.access_token)
      .then(res => res.json())
      .then(response => {
        this.setState({
            videoList: [...this.state.videoList, ...response.results], loading: false
        });
      });
    }

    refreshRecords() {
      fetch('http://######/api/replays/index.php?page=1&ac='+config.access_token)
      .then(res => res.json())
      .then(response => {
        this.setState({
           page: 1, videoList: response.results, isFetching: false
        });
      });
    }

    headerItem() {
      return (   
        <Card style={styles.CardHeader}>
          <Card.Title title="Wisdom Replays" subtitle="A collection of over 60 hours of video content!" left={LeftContentSocialHeader} />
        </Card>
    )}

    renderItem(data) {

      return (   
        <Card style={styles.socialCardPost}>
          <Card.Title title="Rik Courntey" subtitle={data.item.h2} left={LeftContent} />
          <Card.Cover source={{ uri: 'https://bemoresocial.co.uk/images/'+data.item.image }} style={{height: 225}} />
          <Card.Content>
              <Title style={{marginTop: 10}}>{data.item.h1}</Title>
              <Paragraph>{data.item.text}</Paragraph>
          </Card.Content>
        </Card>
    )}

    render() {
      const { videoList, loading } = this.state;

      if(!loading) {
        return (
        <>
          <FlatList
            data={videoList}
            onRefresh={() => this.onRefresh()}
            refreshing={this.state.isFetching}
            ListHeaderComponent = {this.headerItem}
            renderItem={this.renderItem}
            onEndReached={this.onScrollHandler}
            onEndReachedThreshold={1.5}
            showsHorizontalScrollIndicator={false}
            showsVerticalScrollIndicator={false}
          />
        </>
        )
      } else {
          return ( 
          <View
          style={{
            flex: 1,
            justifyContent: 'center',
            alignItems: 'center'
          }}>
            <ActivityIndicator/>
          </View>
          )
    }
  }
}

我希望导航功能可以在WisdomReplays组件的以下元素中显示:

    renderItem(data) {

      return (   
        <Card style={styles.socialCardPost}>
          <Card.Title title="Rik Courntey" subtitle={data.item.h2} left={LeftContent} />
          <Card.Cover source={{ uri: 'https://bemoresocial.co.uk/images/'+data.item.image }} style={{height: 225}} />
          <Card.Content>
              <Title style={{marginTop: 10}}>{data.item.h1}</Title>
              <Paragraph>{data.item.text}</Paragraph>
          </Card.Content>
        </Card>
    )}

我尝试了很多资源,但没有一个对我有用:

https://heartbeat.fritz.ai/getting-started-with-stack-navigator-using-react-navigation-5-in-react-native-and-expo-apps-4c516becaee1

https://medium.com/@shovonroy/how-to-properly-navigate-with-react-navigation-e38fe3bf7381

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

任何帮助将不胜感激:)

1 个答案:

答案 0 :(得分:1)

据我了解-导航道具并未传递到所有组件;只有屏幕组件会自动接收此道具。

我认为您可以尝试直接通过导航道具:

function SocialScreen({ navigation }) {
  return (
    <>
    <Text onPress={() => navigation.navigate('Todo')}> Test </Text>
    <WisdomReplays navigation={navigation}/>
    </>
  );
}

然后在 WisdomReplays 内部使用它:

navigateToSomeWhere = () => {
  this.props.navigation.navigate('Todo');
}

希望这会有所帮助