Retrieve JSON ListView Clicked Item on New Screen React Native Tutorial

Through this tutorial, I am going to explain and show you how we can retrieve JSON ListView  clicked item and show clicked item’s value on new screen from scratch.

In brief, what I am doing in Retrieve JSON ListView Clicked Item on New Screen tutorial?

  • How we can create simple react native ListView  component and render data from JSON in ListView.
  • Fetch clicked item from ListView component and show in new Activity/Screen using StackNavigator.

So let’s begin…

Step – 1: Install react-navigation  library in your react native project. If you have already installed react-navigation  library then you can simply skip this step.

npm install --save react-navigation

Step – 2: Import all required components from react , react-native , react-navigation  packages.

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, ListView, StyleSheet, ActivityIndicator } from 'react-native';

import { StackNavigator } from 'react-navigation';

const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });

Step – 3: Create first custom component, which simply renders a ListView. In my case, first view component’s name is RenderList . You can use any name whatever you want.

class RenderList extends Component
{
    static navigationOptions =
    {
        title: "List Items"
    };

    constructor()
    {
        super();
        this.state = { dataSource: ds.cloneWithRows([]), loading: true };
    }

    componentDidMount()
    {
        // Fetch JSON Data
    }

    // Function to get, pass Clicked Item to new Screen and open New Activity/Screen

    clickedItemText( clickedItem )
    {
        this.props.navigation.navigate('Item', { item: clickedItem });
    }

    render()
    {
        return(
            <View style = { styles.container1 }>
            {
                (this.state.loading)
                ?
                    // Show Activity Indicator until List is not ready
                :
                    // Show ListView component
            }
            </View>
        );
    }
}

Explanation:

  • this.props.navigation.navigate(‘Item’, { item: clickedItem });  statement is used to navigate to second screen (Item) from current screen with clickedItem .

Step – 4: Implement constructor  method of our first custom component RenderList .

componentDidMount()
{
    fetch('https://gamersite123.000webhostapp.com/data.json')
    .then((response) => response.json())
    .then((responseJson) =>
    {
        this.setState({ dataSource: ds.cloneWithRows( responseJson ) }, () => { this.setState({ loading: false }) });
    })
    .catch((error) =>
    {
        console.error(error);
    });
}

Explanation:

  • fetch statement is used to fetch data from server, response.json() method is used to parse fetched json and then set your dataSource  with parsed json and after setting dataSource  state variable we must hide loading indicator(ActivityIndicator) to show ListView component with items.

Step – 5: Implement render  method of RenderList  custom component.

render()
{
    return(
        <View style = { styles.container1 }>
        {
            (this.state.loading)
            ?
                (<ActivityIndicator size = "large"/>)
            :

                (<ListView style = {{ alignSelf: 'stretch' }}
                    dataSource = { this.state.dataSource }
                    renderRow = {( rowData ) =>
                        <TouchableOpacity style = { styles.item } activeOpacity = { 0.4 } onPress = { this.clickedItemText.bind( this, rowData ) }>
                            <Text style = { styles.text }>{ rowData.name.toUpperCase() }</Text>
                        </TouchableOpacity>
                    }
                    renderSeparator = {() =>
                        <View style = { styles.separator }/>
                    }
                    enableEmptySections = { true }/>)
        }
        </View>
    );
}

Step – 6: Create second custom component, which is responsible to shows the selected item of ListView component. In my case, second view component’s name is ClickedItem . You can use any name according to your requirement.

class ClickedItem extends Component
{
    static navigationOptions = 
    {
        title: "Selected Item"
    };

    render()
    {
        return(
            <View style = { styles.container2 }>
                <Text style = { styles.text }>You Selected: { this.props.navigation.state.params.item.name.toUpperCase() }</Text>
            </View>
        );
    }
}

Explanation:

  • this.props.navigation.state.params.item.name.toUpperCase() is used to access the clicked item’s value and then change it to upper case by using the javascript toUpperCase()  function.

Step – 7: Register both screens/custom components into StackNavigator  to enable navigation.

export default App = StackNavigator(
{
    List: { screen: RenderList },
    Item: { screen: ClickedItem }
});

Step – 8: Implement styles for all required components.

const styles = StyleSheet.create(
{
    container1:
    {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
    },

    container2:
    {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        paddingHorizontal: 15
    },

    item:
    {
        padding: 15
    },

    text:
    {
        fontSize: 18
    },

    separator:
    {
        height: 2,
        backgroundColor: 'rgba(0,0,0,0.5)'
    }
});

Complete Source Code:

import React, { Component } from 'react';
import { View, Text, TouchableOpacity, ListView, StyleSheet, ActivityIndicator } from 'react-native';

import { StackNavigator } from 'react-navigation';

const ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 !== r2 });

class RenderList extends Component
{
    static navigationOptions =
    {
        title: "List Items"
    };

    constructor()
    {
        super();
        this.state = { dataSource: ds.cloneWithRows([]), loading: true };
    }

    componentDidMount()
    {
        fetch('https://gamersite123.000webhostapp.com/data.json')
        .then((response) => response.json())
        .then((responseJson) =>
        {
            this.setState({ dataSource: ds.cloneWithRows( responseJson ) }, () => { this.setState({ loading: false }) });
        })
        .catch((error) =>
        {
            console.error(error);
        });
    }

    clickedItemText( clickedItem )
    {
        this.props.navigation.navigate('Item', { item: clickedItem });
    }

    render()
    {
        return(
            <View style = { styles.container1 }>
            {
                (this.state.loading)
                ?
                    (<ActivityIndicator size = "large"/>)
                :

                    (<ListView style = {{ alignSelf: 'stretch' }}
                        dataSource = { this.state.dataSource }
                        renderRow = {( rowData ) =>
                            <TouchableOpacity style = { styles.item } activeOpacity = { 0.4 } onPress = { this.clickedItemText.bind( this, rowData ) }>
                                <Text style = { styles.text }>{ rowData.name.toUpperCase() }</Text>
                            </TouchableOpacity>
                        }
                        renderSeparator = {() =>
                            <View style = { styles.separator }/>
                        }
                        enableEmptySections = { true }/>)
            }
            </View>
        );
    }
}

class ClickedItem extends Component
{
    static navigationOptions = 
    {
        title: "Selected Item"
    };

    render()
    {
        return(
            <View style = { styles.container2 }>
                <Text style = { styles.text }>You Selected: { this.props.navigation.state.params.item.name.toUpperCase() }</Text>
            </View>
        );
    }
}

export default App = StackNavigator(
{
    List: { screen: RenderList },
    Item: { screen: ClickedItem }
});


const styles = StyleSheet.create(
{
    container1:
    {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center'
    },

    container2:
    {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        paddingHorizontal: 15
    },

    item:
    {
        padding: 15
    },

    text:
    {
        fontSize: 18
    },

    separator:
    {
        height: 2,
        backgroundColor: 'rgba(0,0,0,0.5)'
    }
});

Step – 9: As usual use react-native run-android  to run app in Android devices and use react-native run-ios  to run app in iOS devices.

  • iOS Screenshots:

  • Android Screenshots:

 

2 Comments

  1. Everything is very open with a precise clarification of the challenges.
    It was definitely informative. Your site is very useful.

    Thank you for sharing!

Leave a Reply

Your email address will not be published. Required fields are marked *