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:
Everything is very open with a precise clarification of the challenges.
It was definitely informative. Your site is very useful.
Thank you for sharing!
Thanks Cole.