【问题标题】:How to nest Stack Navigator inside a Drawer Navigator with navigation v5+如何使用导航 v5+ 将 Stack Navigator 嵌套在 Drawer Navigator 中
【发布时间】:2021-01-21 15:42:12
【问题描述】:

我的项目结构是这样的:

  • app.js(加载数据和抽屉导航器)

  • MainScreen(在预览模式下使用之前获取的数据加载卡片,当您单击时,您有一个 NewsComponent 可以获取该记录的完整数据)

  • NewsScreen(使用之前获取的数据加载整篇文章)

在我的 App.js 中,我正在使用这样的抽屉导航器:

return (
      <NavigationContainer>
        <Drawer.Navigator initialRouteName="Main">
          <Drawer.Screen name="Main" options={{ headerShown: false}}>
            {props => <MainScreen {...props} extraData={App.news} />}
          </Drawer.Screen>
          <Drawer.Screen name="Court Reservation" component={CourtReservation}></Drawer.Screen>
          <Drawer.Screen name="News" component={NewsScreen}></Drawer.Screen>
        </Drawer.Navigator>
      </NavigationContainer>
    );
  }

但我需要在 Main 组件中插入一个堆栈导航器以显示记录 (NewsScreen),因为如果不是当我返回列表 (Main) 并再次返回到不同的记录时,内容不会更新并且正在显示第一条记录。

我尝试了几次,但我得到了各种各样的错误。现在我的 MainScreen 是这样的:

render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button onPress={() => this.props.navigation.openDrawer()} transparent>
              <Icon name='menu' />
            </Button>
          </Left>
          <Body>
            <Title>Header</Title>
          </Body>
          <Right />
        </Header>
        <FlatList
          data={this.state.news}
          onEndReached={this.fetchMoreNews}
          onEndReachedThreshold={0.5}
          keyExtractor={(item, index) => index.toString()}
          renderItem={({item}) => (
            <Content>
          <CardNewsComponent data={item} nav={this.props.navigation}/>
          </Content>
          )}/>
        </Container>
    );
  }

但是正在使用抽屉导航命令来“导航”到组件。

我如何集成堆栈导航器来做到这一点?


编辑:

在那种遮阳篷之后,我的 app.js 是这样的:

    import * as React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createDrawerNavigator } from '@react-navigation/drawer';
import { createStackNavigator } from '@react-navigation/stack';
import MainScreen from './screens/MainScreen';
import NewsScreen from './screens/NewsScreen';
import CourtReservation from './screens/CourtReservation';
import * as SplashScreen from 'expo-splash-screen';
import * as Font from 'expo-font';
import { Ionicons } from '@expo/vector-icons';
import axios from 'axios';


const Drawer = createDrawerNavigator();
const Stack = createStackNavigator();

const myStack = (<Stack.Navigator initialRouteName="Main">
              <Stack.Screen name="Main" options={{ headerShown: false}}>
                {props => <MainScreen {...props} extraData={App.news} />}
              </Stack.Screen>
              <Stack.Screen name="News" component={NewsScreen}></Stack.Screen>
            </Stack.Navigator>)
       

export default class App extends React.Component {
  state = {
    appIsReady: false,
  };

  news = {};

  async componentDidMount() {
    // Prevent native splash screen from autohiding
    try {
      await SplashScreen.preventAutoHideAsync();
    } catch (e) {
      console.warn(e);
    }
    this.prepareResources();
  }

  /**
   * Method that serves to load resources and make API calls
   */
  prepareResources = async () => {
    await performAPICalls();
    await downloadAssets();

    this.setState({ appIsReady: true }, async () => {
      await SplashScreen.hideAsync();
    });
  };

  render() {
    if (!this.state.appIsReady) {
      return null;
    }

    return (
      <NavigationContainer>
        <Drawer.Navigator initialRouteName="Main">
          <Drawer.Screen name="Main" component={myStack}></Drawer.Screen>
          <Drawer.Screen name="Court Reservation" component={CourtReservation}></Drawer.Screen>
        </Drawer.Navigator>
      </NavigationContainer>
    );
  }
}

// Put any code you need to prepare your app in these functions
async function performAPICalls() {
  await axios.get('https://alqueriadelbasket.com/?r=noticias/FetchNoticiasJson&boundBot=0&boundTop=5')
    .then((response) => {
      App.news = response.data;
    }).catch((error)=> {
      console.log(error);
    })
}
async function downloadAssets() {
    await Font.loadAsync({
      Roboto: require('native-base/Fonts/Roboto.ttf'),
      Roboto_medium: require('native-base/Fonts/Roboto_medium.ttf'),
      ...Ionicons.font,
  });
}

还有我的主屏幕

import React, { Component } from 'react';
import { Container, Content, Header, Left, Button, Icon, Right, Body, Title} from 'native-base';
import {FlatList} from 'react-native';
import CardNewsComponent from './components/CardNewsComponent';
import axios from 'axios';

export default class MainScreen extends Component {
  constructor(props){
    super(props);
    this.state = {
      news: this.props.extraData,
      boundBot: 6,
      bountTop: 11,
      error: null,
    };
  }

  fetchMoreNews = () => {
    axios.get(`https://alqueriadelbasket.com/?r=noticias/FetchNoticiasJson&boundBot=${this.state.boundBot}&boundTop=${this.state.bountTop}`)
    .then((response) => {
      this.setState({
        boundBot: this.state.boundBot+5,
        boundTop: this.state.boundTop+5,
        news: this.state.news.concat(response.data)
      })
    }).catch((error)=> {
      console.log(error);
    })
  }

  newsData = this.props.extraData;
  render() {
    return (
      <Container>
        <Header>
          <Left>
            <Button onPress={() => this.props.navigation.openDrawer()} transparent>
              <Icon name='menu' />
            </Button>
          </Left>
          <Body>
            <Title>Header</Title>
          </Body>
          <Right />
        </Header>
        <FlatList
          data={this.state.news}
          onEndReached={this.fetchMoreNews}
          onEndReachedThreshold={0.5}
          keyExtractor={(item, index) => index.toString()}
          renderItem={({item}) => (
            <Content>
          <CardNewsComponent data={item} nav={this.props.navigation}/>
          </Content>
          )}/>
        </Container>
    );
  }
}

错误是“Get an invalid value for 'component' prop for the screen Main, It must be a valid react component.

有趣的是,Main 之前的工作就像一个魅力......:/


EDIT2:

在尝试查看官方文档后。

这就是问题所在:

它不能是一个常量,它必须是一个函数......所以我将把这个函数添加到抽屉导航中,它就像一个魅力。

代码如下:

function MyStack() {
  return (
    <Stack.Navigator initialRouteName="Main">
              <Stack.Screen name="Main" options={{ headerShown: false}}>
                {props => <MainScreen {...props} extraData={App.news} />}
              </Stack.Screen>
              <Stack.Screen name="News" component={NewsScreen}></Stack.Screen>
            </Stack.Navigator>
  );
}

【问题讨论】:

  • 只是在黑暗中的一个镜头,你能把myStack重命名为MyStack吗?这是一个可能的原因
  • 仍然无法正常工作,同样的错误,在 Const... 和 DrawerNav component={...} 中重命名还有其他猜测吗?
  • 我只是找到了我将在主要问题中提出的解决方案。

标签: javascript react-native react-navigation


【解决方案1】:

在抽屉导航器中,我们有抽屉屏幕

  <Drawer.Navigator initialRouteName="Main">
     <Drawer.Screen name="Main" options={{ headerShown: false}}>
     ......
     //you can add a Stack Navigator as a screen here

  </Drawer.Navigator>

所以你可以在上面定义一个堆栈导航器:

  const MyStack = <Stack.Navigator>
                  //your stack screens     
                  ......
                 </Stack.Navigator>

然后,将其用作抽屉屏幕:

<Drawer.Screen name="main" component={MyStack} />

【讨论】:

  • 通过编辑我得到“未定义不是一个对象(评估“Stack.Navigator”有什么猜测吗?
  • 我认为您错过了导入声明:import { createStackNavigator } from '@react-navigation/stack';
  • 是的,对不起,我以为我再次编辑了,错误是:“屏幕 Main 的 'component' prop 的值无效,它必须是有效的反应组件。(检查 main awnser再次感谢)
猜你喜欢
  • 2021-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-24
  • 2020-02-06
  • 2021-12-26
  • 2018-07-30
  • 1970-01-01
相关资源
最近更新 更多