将用户导航到 listitem 上的新屏幕单击 React native

Posted

技术标签:

【中文标题】将用户导航到 listitem 上的新屏幕单击 React native【英文标题】:Navigate user to New Screen on listitem click React native 【发布时间】:2017-11-16 05:22:48 【问题描述】:

试图在用户单击列表项时将用户导航到下一个屏幕。我正在尝试在这方面使用 Navigator,我是新手,有 Redux 和 Flux 两种不同的架构,因为我的反应不是很好,所以我对那里的工作有点困惑。我们可以使用 Navigator 和 Action 来导航用户。这是我的课:-

我遇到的错误是:- 未定义不是函数(正在评估'_this4.goDetailPage(rowData)')

Today.js

    import React,  Component  from 'react';
import 
  StyleSheet,
  Text,
 from 'react-native';
import FeedStack from './movielistdeatilrouter';

export default class TodayView extends Component 
 constructor(props , context) 
      super(props , context);
    
   render() 
        return (
<FeedStack />
        );
    
 

movielistdeutilrouter.js:-

import React from 'react';
import StackNavigator  from 'react-navigation';
import MovieDeatilScreen from './MovieDeatilScreen';
import Movielisting from './movielisting';
export const FeedStack = StackNavigator(
  Movielisting: 
    screen: Movielisting,
    navigationOptions: 
      title: 'Movielisting',
    ,
  ,
  MovieDeatilScreen: 
    screen: MovieDeatilScreen,
    navigationOptions: ( navigation ) => (
      title: 'MovieDeatilScreen',
    ),
  ,
);

movielistiing.js :-

import React,  Component  from 'react';
import  StatusBar  from 'react-native'
import  StackNavigator  from 'react-navigation';
import  NavigationActions  from 'react-navigation';
import  Actions, ActionConst  from 'react-native-router-flux';
import home  from '../images/home.png';
import MovieDeatilScreen from './MovieDeatilScreen'
const  width: viewportWidth, height: viewportHeight  = Dimensions.get('window');
import 
  StyleSheet,
  Text,
  Image,
  View,
  AsyncStorage,
  TouchableOpacity,
  TouchableHighlight,
  Dimensions,
  ListView
 from 'react-native';
const uri = 'http://csswrap.com/wp-content/uploads/2015/03/showmenu.png';
export default class Movielisting extends Component 

 constructor(props) 
     super(props);
     var ds = new ListView.DataSource(rowHasChanged: (r1, r2) => r1 !== r2);
     this.state = 
       moviesData: ds.cloneWithRows([]),
     ;
   

   componentDidMount() 
       this.fetchMoviesData();
     
      fetchMoviesData() 
          var url = 'http://api.themoviedb.org/3/movie/now_playing?api_key=17e62b78e65bd6b35f038505c1eec409';
          fetch(url)
            .then(response => response.json())
            .then(jsonData => 
              this.setState(
                moviesData: this.state.moviesData.cloneWithRows(jsonData.results),

              );
            )
          .catch( error => console.log('Error fetching: ' + error) );
        
  render() 
        return (
                <View style=styles.container>

                    <ListView
                      dataSource=this.state.moviesData
                            renderRow=this.renderRow
                            enableEmptySections=true
                             style=styles.ListViewcontainer
                          />
                    </View>
        );
    
    renderRow(rowData)
            return (
              <View style=styles.thumb >
              <TouchableOpacity  onPress=() => this.goDeatilPage(rowData)>
                <Image
                  source=uri:'https://image.tmdb.org/t/p/w500_and_h281_bestv2/'+rowData.poster_path
                  resizeMode="cover"
                  style=styles.img />
                  <Text style=styles.txt>rowData.title (Rating: Math.round( rowData.vote_average * 10 ) / 10)</Text>
              </TouchableOpacity>
              </View>

            );
          
goDeatilPage = (rowData) => 
   alert('hi');
   AsyncStorage.setItem('moviesData', JSON.stringify(rowData));
       this.props.navigation.navigate('MovieDeatilScreen');
     ;

const styles = StyleSheet.create(
  container: 
  position:'relative',
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  ,
  welcome: 
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  ,action: 
                                        flex: 0.4,
                                    ,thumb: 
                                          backgroundColor: '#ffffff',
                                          marginBottom: 5,
                                          elevation: 1
                                        ,
                                        img: 
                                          height: 300
                                        ,
                                        txt: 
                                          margin: 10,
                                          fontSize: 16,
                                          textAlign: 'left'
                                        ,ListViewcontainer:
                                         marginTop:50,
                                          bottom: 50,
                                        
);

Index.android.js :-

import React,  Component  from 'react';
import 
  AppRegistry,
  StyleSheet,
  Text,
  StatusBar,
  View
 from 'react-native';
import App from './app';
import DrawerMenu from './Drawer/drawer-toolbar-android';
import BookmarkView from './Pages/bookmark';
import CalendarView from './Pages/calendar';
import ClientView from './Pages/client';
import InfoView from './Pages/info';
import SettingsView from './Pages/setting';
import  DrawerNavigator, StackNavigator  from 'react-navigation';


const stackNavigator = StackNavigator(
  Info:  screen: InfoView ,
  Settings: screen: SettingsView ,
  Bookmark: screen: BookmarkView ,
  Calendar: screen: CalendarView,
  Client: screen: ClientView,
, 
  headerMode: 'none'
);

const easyRNRoute = DrawerNavigator(
  Home: 
    screen: App,
  ,
  Stack: 
    screen: stackNavigator
  
, 
  contentComponent: DrawerMenu,
  contentOptions: 
    activeTintColor: '#e91e63',
    style: 
      flex: 1,
      paddingTop: 15,
    
  
);

AppRegistry.registerComponent('flightbot', () => easyRNRoute);

App.js 类 :-

import React,  Component  from 'react';
import 
  AppRegistry,
  StyleSheet,
  Text,
  StatusBar,
  View
 from 'react-native';
import  Navigator, NativeModules  from 'react-native';

import  COLOR, ThemeProvider  from 'react-native-material-ui';
import  Toolbar, BottomNavigation, Icon  from 'react-native-material-ui';
import Container from './Container';

import  TabRouter  from 'react-navigation';

import TodayView from './Contents/today';
import ProfileView from './Contents/profile';
import MapView from './Contents/map';
import ChatView from './Contents/chat';

const uiTheme = 
  palette: 
    primaryColor: COLOR.green500,
    accentColor: COLOR.pink500,
  ,
  toolbar: 
    container: 
      height: 70,
      paddingTop: 20
    
  


const TabRoute = TabRouter(
  Today:  screen: TodayView ,
  Profile:  screen: ProfileView ,
  Map:  screen: MapView ,
  Chat: screen: ChatView
  , 
    initialRouteName: 'Today',
  
);

class TabContentNavigator extends Component 
  constructor(props, context) 
    super(props, context);
    this.state = 
      active: props.value.active,
    ;
  

  //this method will not get called first time
  componentWillReceiveProps(newProps)
    this.setState(
      active: newProps.value.active,
    ); 
  

  render() 
    const Component = TabRoute.getComponentForRouteName(this.state.active);
    return <Component/>;
  


export default class App extends Component 
  constructor(props, context) 
    super(props, context);

    this.state = 
      active: 'Today',
    ;
  

  static navigationOptions = 
    title: 'Menu',
  ;

  navigate() 
    this.props.navigation.navigate('DrawerOpen'); // open drawer
  

  render() 
    return (
      <ThemeProvider uiTheme=uiTheme>
        <Container>
          <StatusBar backgroundColor="rgba(0, 0, 0, 0.2)" translucent />

          <Toolbar
            leftElement="menu"
            centerElement=this.state.active
            onLeftElementPress=() => this.navigate()
          />

          <TabContentNavigator value=this.state key=this.state />

          <BottomNavigation active=this.state.active
            hidden=false
            style= container:  position: 'absolute', bottom: 0, left: 0, right: 0  
          >
            <BottomNavigation.Action
              key="Today"
              icon="today"
              label="Today"
              onPress=() => this.setState( active: 'Today' )
            />
            <BottomNavigation.Action
              key="Profile"
              icon="person"
              label="Profile"
              onPress=() => 
                this.setState( active: 'Profile' );
              
            />
            <BottomNavigation.Action
              key="Map"
              icon="map"
              label="Map"
              onPress=() => this.setState( active: 'Map' )
            />
            <BottomNavigation.Action
              key="Chat"
              icon="chat"
              label="Chat"
              onPress=() => this.setState( active: 'Chat' )
            />
          </BottomNavigation>

        </Container>
      </ThemeProvider>
    );
  

我正在尽我最大的努力来解决这个问题,今天已经快 3 天了,我正在寻找解决方案,我该如何做到这一点,我只想在单击列表项时打开一个新屏幕。谁能告诉我该怎么做。如果有人让我知道导航到下一个屏幕的方式,我将非常感激。

我的错误截图:-

谢谢!!!

【问题讨论】:

【参考方案1】:

使用“React Navigation”应该可以帮助您解决问题。

欲了解更多信息,您可以在这里找到:https://reactnavigation.org

干杯,

====== 更新 ======

我认为您设置 Today 组件的方式不正确,而且您的问题也不清楚,我花了一段时间才明白您想要做什么。

无论如何,Today 组件应该是一个 StackNavigator,如果你想从中打开一个详细屏幕,它将控制 2 个屏幕(ListScreen 和 DetailScreen):

const TodayView = StackNavigator(
  List: 
    screen: ListScreen,
  ,
  Detail: 
    screen: DetailScreen,
  ,
);

然后像这样设置你的屏幕:

class ListScreen extends Component 
  static navigationOptions = 
    title: 'List',
  

  constructor(props , context) 
    super(props , context);
    this.goToDetailScreen = this.goToDetailScreen.bind(this);
  

  goToDetailScreen() 
    this.props.navigation.navigate('Detail');
  

  render() 
    return (
      <TouchableOpacity onPress=() => this.goToDetailScreen()>
        <Text>GO TO DETAIL</Text>
      </TouchableOpacity>
    );
  


class DetailScreen extends Component 
  static navigationOptions = 
    title: 'Detail',
  

  render() 
    return (
      <TouchableOpacity onPress=() => this.props.navigation.goBack()>
        <Text>BACK TO LIST SCREEN</Text>
      </TouchableOpacity>
    );
  

在他们的 Github 存储库中有一个名为“StacksInTabs”的示例,您可能想看看它:https://github.com/react-community/react-navigation/blob/master/examples/NavigationPlayground/js/StacksInTabs.js

干杯,

【讨论】:

你好@Goon,谢谢你的回复,是的,我之前看过这个,问题是上面的类在我的 TabRouter 下,当我尝试声明 const navigate = this.props.navigation; 它给了我错误,因为 Undefined is not an object(evalating this.props.navigation.navigate) ,让我发布我剩下的课程,我正在从一个链接学习并尝试理解流程.,请查看我更新的问题。让我在上面的课程中使用这种方法。谢谢 只需更新答案,让我知道它是否有效@sid :) 嘿@Goon,我有点困惑,问题出在 Today.js 类中,我无法使用 RenderRow 函数中的 onpress 事件调用导航器,我也像你一样更新了我的 App.js 文件上面提到,但仍然无法在单击 ListItem 时导航到详细信息屏幕。 是的,我已经研究了链接,并按照您提到的方式相应地更改了我的流程,但是我的函数没有被调用,我知道我可能会犯一些愚蠢的错误让我更新我的问题你。 嘿@GoonNguyen。感谢您的回复。您上次共享的 Git 存储库无法访问。你能更新那个链接吗?谢谢【参考方案2】:

终于成功了,这就是我在更改代码后所做的事情。 :-

<View style=styles.container>
                    <ListView
                      dataSource=this.state.moviesData
                            renderRow=this.renderRow.bind(this)
                            enableEmptySections=true
                             style=styles.ListViewcontainer
                          />
                    </View>

我刚刚在 renderRow 中添加了 .bind(this) 函数。

休息是一样的:-

renderRow(rowData)
            return (
              <View style=styles.thumb >
              <TouchableOpacity  onPress=()=>this.goDeatilPage(rowData)>
                <Image
                  source=uri:'https://image.tmdb.org/t/p/w500_and_h281_bestv2/'+rowData.poster_path
                  resizeMode="cover"
                  style=styles.img />
                  <Text style=styles.txt>rowData.title (Rating: Math.round( rowData.vote_average * 10 ) / 10)</Text>
              </TouchableOpacity>
              </View>

            );
          
goDeatilPage = (rowData) => 
   alert('hi');
   AsyncStorage.setItem('moviesData', JSON.stringify(rowData));
       this.props.navigation.navigate('MovieDeatilScreen');
     

感谢@Goon 抽出宝贵时间,非常感谢您的努力。谢谢大哥。

【讨论】:

告诉你,伙计。我确实试图告诉您在第一时间检查绑定功能:D 很高兴能帮上忙!【参考方案3】:

使用 React Navigation 导航屏幕,非常易于使用,

在 react native 中创建 3 个类
    定义的导航器类 2.第一屏 3.导航屏幕

1.Basic.js

    import 
  StackNavigator,
 from 'react-navigation';

const BasicApp = StackNavigator(
  Main: screen: Movielistiing,
  Detail: screen: Movielistdeatilrouter,
);
module.exports = BasicApp;

2.Movielistiing.js

class Movielistiing extends React.Component 
  static navigationOptions = 
    title: 'Welcome',
  ;
  render() 
    const  navigate  = this.props.navigation;
    return (
      <Button
        title="Go to movie detail"
        onPress=() =>
          navigate('Detail',  name: 'Jane' )
        
      />
    );
  

3.Movielistdeutilrouter.js

class Movielistdeatilrouter extends React.Component 
  static navigationOptions = (navigation) => (
    title: navigation.state.params.name,
  );
  render() 
    const  goBack  = this.props.navigation;
    return (
      <Button
        title="Go back"
        onPress=() => goBack()
      />
    );
  

【讨论】:

以上是关于将用户导航到 listitem 上的新屏幕单击 React native的主要内容,如果未能解决你的问题,请参考以下文章

如何将用户重定向到 div 上的新页面单击 JQuery [重复]

swiftUI:登录完成后导航到主屏幕。通过按钮单击导航视图

以编程方式导航到 SwiftUI 中的新视图

一旦用户导航到Javascript中的新页面,就禁止用户使用后退按钮[重复]

单击按钮导航到root viewcontroller

Flutter 再次触发 bloc 事件