I can't display json data in listview. I get json data in console.log but not in listview isLoading is always on false.
I dont get any errors .catch(error => console.warn("error")).
Result on screen is first View because this.state.isLoading is false.
Here is a code:
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, ListView, Text, View,Image,TouchableHighlight } from 'react-native';
var productArray = [];
class ListViewDemo extends Component {
constructor(props) {
console.warn("constructor");
super(props);
var dataSource = new ListView.DataSource({rowHasChanged:(r1,r2) => r1.guid != r2.guid});
this.state = {
dataSource: dataSource.cloneWithRows(productArray),
isLoading:true
}
}
componentDidMount() {
console.warn("componentDidMount");
this.getTheData(function(json){
productArray = json;
console.warn(productArray);
this.setState = ({
datasource:this.state.dataSource.cloneWithRows(productArray),
isLoading:false
})
}.bind(this));
console.warn("component -> " + this.state.isLoading);
}
getTheData(callback) {
console.warn("callback");
var url = "https://raw.githubusercontent.com/darkarmyIN/React-Native-DynamicListView/master/appledata.json";
fetch(url)
.then(response => response.json())
.then(json => callback(json))
.catch(error => console.warn("error"));
}
renderRow(rowData, sectionID, rowID) {
console.warn("renderRow");
return (
<TouchableHighlight underlayColor='#dddddd' style={{height:44}}>
<View>
<Text style={{fontSize: 20, color: '#000000'}} numberOfLines={1}>{rowData.display_string}</Text>
<Text style={{fontSize: 20, color: '#000000'}} numberOfLines={1}>test</Text>
<View style={{height: 1, backgroundColor: '#dddddd'}}/>
</View>
</TouchableHighlight>
);
}
render() {
console.warn("render" + this.state.isLoading);
var currentView = (this.state.isLoading) ? <View style={{height: 110, backgroundColor: '#dddddd'}} /> : <ListView dataSource={this.state.dataSource} renderRow={this.renderRow.bind(this)} enableEmptySections={true}/>
return(
<View>
{currentView}
</View>
);
}
}
// App registration and rendering
AppRegistry.registerComponent('AwesomeProject', () => ListViewDemo);
I see a couple of mistakes here.
In your componentDidMount, you are setting datasource intead of dataSource:
componentDidMount() {
console.warn("componentDidMount");
this.getTheData(function(json){
productArray = json;
console.warn(productArray);
this.setState = ({
//datasource:this.state.dataSource.cloneWithRows(productArray),
dataSource:this.state.dataSource.cloneWithRows(productArray),
isLoading:false
})
}.bind(this));
console.warn("component -> " + this.state.isLoading);
}
That's why you're not being able to render, because dataSource is never populated. It is just a little spelling mistake.
You are probably not getting into the second then in your getTheData method because you are not returning a Promise:
getTheData(callback) {
console.warn("callback");
var url = "https://raw.githubusercontent.com/darkarmyIN/React-Native-DynamicListView/master/appledata.json";
fetch(url)
//.then(response => response.json())
.then(response => return response.json())
.then(json => callback(json))
.catch(error => console.warn("error"));
}
Your are making a mistake with your setState, your are assigning it instead of calling it:
//this.setState = ({
// datasource:this.state.dataSource.cloneWithRows(productArray),
// isLoading:false
//})
this.setState({
dataSource:this.state.dataSource.cloneWithRows(productArray),
isLoading:false
})
Let me know if it works.
You are setting the function setState instead of calling it
this.setState = ({
datasource:this.state.dataSource.cloneWithRows(productArray),
isLoading:false
})
should be
this.setState({
datasource:this.state.dataSource.cloneWithRows(productArray),
isLoading:false
})
Related
I'm making a list view were I will view a list of some data from my database. But after running the program all I got is white background screen. Does anyone knows the solution?
screen shot
Here is my code
export default class Pasta extends Component {
constructor() {
super()
this.state = {
dataSource: []
}
}
renderItem = ({ item }) => {
return (
<View style = {{flex: 1, flexDirection: 'row'}}>
<View style = {{flex: 1, justifyContent: 'center'}}>
<Text>
{item.menu_desc}
</Text>
<Text>
{item.menu_price}
</Text>
</View>
</View>
)
}
componentDidMount() {
const url = 'http://192.***.***.***:9090/menu'
fetch(url)
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.menu
})
})
}
render() {
return (
<View style = { styles.container }>
<FlatList
data = { this.state.dataSource }
renderItem = {this.renderItem}
/>
</View>
);
}
}
Add extraData prop to your FlatList to cause a re-render
keyExtractor = (item, index) => item.id; // note: id is the unique key for each item
render() {
return (
<FlatList
data = {this.state.dataSource}
renderItem = {this.renderItem}
extraData={this.state}
keyExtractor={this.keyExtractor}
/>
);
}
Also log and verify your data is present. I suggest referring to FlatList docs for more props like keyExtractor etc.
I want to fetch multiple API requests in componentDidMount() function. I have a picker which take items from API call. I have another API which returns a picker value. Now i want to set selected the value received in latter API in the picker. I am trying to fetch both API in componentDidMount function
Here is my code. Please suggest where i am missing.
import React, { Component } from 'react';
import { AppRegistry, StyleSheet, View, Platform, Picker, ActivityIndicator, Button, Alert} from 'react-native';
export default class FirstProject extends Component {
constructor(props)
{
super(props);
this.state = {
isLoading: true,
PickerValueHolder : ''
}
}
componentDidMount() {
const base64 = require('base-64');
// my API which fetches picker items
return fetch('https://reactnativecode.000webhostapp.com/FruitsList.php')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
// another api which fetches a particular fruit_id from database which i ave to set selected in picker.
fetch('http://my_api_url', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
"fruit_id":"123"
})
}).then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
PickerValueHolder: responseJson,
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
GetPickerSelectedItemValue=()=>{
Alert.alert(this.state.PickerValueHolder);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<Picker
selectedValue={this.state.PickerValueHolder}
onValueChange={(itemValue, itemIndex) => this.setState({PickerValueHolder: itemValue})} >
{ this.state.dataSource.map((item, key)=>(
<Picker.Item label={item.fruit_name} value={item.fruit_name} key={key} />)
)}
</Picker>
<Button title="Click Here To Get Picker Selected Item Value" onPress={ this.GetPickerSelectedItemValue } />
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: 'center',
flex:1,
margin: 10
}
});
As you said in comment, your second API response:
[{"fruit_id": "123","fruit_name":"Strwaberry"}]
So it might work with minor changes:
.then((responseJson) => {
this.setState({
isLoading: false,
PickerValueHolder: responseJson[0].fruit_name,
}, function() {
// In this block you can do something with new state.
});
})
Hello fellow programmers, I am having this problem developing this React-Native app where i am rendering a ListView of 'Services' where in each row it has a Text and a Switch, and I am able to render it but when i tap on the row's switch to change the value it goest back to its initial value real fast, I was wondering how to keep this change of vale but since I am new into this I am pretty clueless of how this is done: so far I have the ListView component where I call my ListItem component, heres my code;
class ListView extends Component {
constructor(props) {
super(props);
this.state = {
servicios: []
};
}
componentDidMount() {
AsyncStorage.getItem("token").then((value) => {
axios.get('http://MYURL/api/servicio/index?token=' + value)
.then(response => this.setState({ servicios: response.data.servicios }))
.catch(function (error) {
console.log(error);
});
}).done();
}
renderList() {
console.log('here');
return this.state.servicios.map(servicio =>
<ListItem key={servicio.id} servicio={servicio} />);
}
render() {
const { navigation } = this.props.navigation;
return (
<ScrollView>
{this.renderList()}
</ScrollView>
);
}
}
ListItem.js
const ListItem = ({ servicio }) => {
const { nombre, created_at, estatus } = servicio;
const { thumbnailStyle, headerContentStyle, thumbnailContainerStyle, headerTextStyle, imageStyle } = styles;
return (
<Card>
<CardSection>
<View style={thumbnailContainerStyle}>
<Text style={headerTextStyle}>{nombre}</Text>
</View>
<View style={headerContentStyle}>
<Switch value={estatus}/>
</View>
</CardSection>
</Card>
);
export default ListItem;
I missed the styles to not make this post too long, I may have the clue that i've got to put the current's row switch status in the State but I dont know how to do it, I would be really glad if you guys could help me?
Thanks in advance.
In order to change value of the switch you need to change value in the state from which you're rendering the ListView. I haven't tested that and wrote that from the top of my head, but you should achieve it by introducing small changes here and there:
ListItem.js
const ListItem = ({ servicio, onToggleSwitch }) => {
const { nombre, created_at, estatus, id } = servicio;
const { thumbnailStyle, headerContentStyle, thumbnailContainerStyle, headerTextStyle, imageStyle } = styles;
return (
<Card>
<CardSection>
<View style={thumbnailContainerStyle}>
<Text style={headerTextStyle}>{nombre}</Text>
</View>
<View style={headerContentStyle}>
<Switch value={estatus} onValueChange={(value) => onToggleSwitch(id, value)} />
</View>
</CardSection>
</Card>
);
export default ListItem;
ListView.js
class ListView extends Component {
constructor(props) {
super(props);
this.state = {
servicios: []
};
}
onToggleSwitch = (id, value) => {
const servicios = [...this.state.servicios]
const index = servicios.findIndex(item => item.id === id)
servicios[index].estatus = value
this.setState({ servicios })
}
componentDidMount() {
AsyncStorage.getItem("token").then((value) => {
axios.get('http://MYURL/api/servicio/index?token=' + value)
.then(response => this.setState({ servicios: response.data.servicios }))
.catch(function (error) {
console.log(error);
});
}).done();
}
renderList() {
console.log('here');
return this.state.servicios.map(servicio =>
<ListItem key={servicio.id} servicio={servicio} onToggleSwitch={this.onToggleSwitch} />);
}
render() {
const { navigation } = this.props.navigation;
return (
<ScrollView>
{this.renderList()}
</ScrollView>
);
}
}
i want to display my JSON in a Listview. the problem is i dont know how to use code for display my JSON data
enter image description here
this is my JSON respone. i want to show nama and harga_jual
import React, { Component } from 'react';
import {
StyleSheet,
Text,
AsyncStorage,
Alert,
ListView,
View
} from 'react-native';
import { Actions } from 'react-native-router-flux';
import { Header, Container, Content, Icon, Left, Body, Right, Button, Title, Card, CardItem, Thumbnail} from 'native-base';
export default class Product extends Component {
constructor(props) {
super(props);
var dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
});
this.state={
iduser: '',
idgrup_outlet: '',
url:'',
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
}
}
async componentWillMount() {
const value = await AsyncStorage.getItem('iduser').then((value) => {
this.setState({
'iduser': value
});
console.log("ID User is : " + this.state.iduser);
})
const value1 = await AsyncStorage.getItem('idgrup_outlet').then((value) => {
this.setState({
'idgrup_outlet': value
});
console.log("ID Group Outlet is : " +(this.state.idgrup_outlet));
})
const value2 = await AsyncStorage.getItem('url').then((value) => {
this.setState({
'url': value
});
console.log("URL is : " + this.state.url);
})
console.log("ID User is : " + this.state.iduser);
let response = await fetch('http://'+this.state.url+'/web_services/list_produk/new.json', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
erzap: {
iduser: this.state.iduser,
idgrup_outlet: this.state.idgrup_outlet,
}
})
});
let responseJson = await response.json();
// console.log(JSON.stringify(responseJson.produks[nama]));
console.log(JSON.stringify(responseJson.produks));
}
render() {
return (
<Container>
<Header style={{backgroundColor: '#03A9F4'}}>
<Left>
<Button transparent>
<Icon name='menu'/>
</Button>
</Left>
</Header>
<Content>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData.nama}</Text>}
/>
</Content>
</Container>
);
}
}
const styles = StyleSheet.create({
carditem: {
paddingLeft: 10,
},
});
this my code
What you can do here is to set the state of your dataSource to responseJson in the componentWillMount method. So it would look something like this:
// ... the rest of the code
let responseJson = await response.json();
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseJson),
});
I have this piece of react-native code:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
ToolbarAndroid,
ListView,
Text,
View
} from 'react-native';
let styles = require('./styles/styles');
class Sunshine extends Component {
constructor(props) {
super(props);
this.state = {isLoading: true, jsonData: ''}
}
componentDidMount() {
this.setState({jsonData: this.getMoviesFromApiAsync()})
}
render() {
if(this.state.isLoading != true) {
return (
<View style={styles.container}>
<ToolbarAndroid
style={styles.baseToolbar}
logo={require('./ic_launcher.png')}
title="Sunshine"
titleTextColor="red"/>
<View style={styles.viewcontainer}>
<Text>{this.state.jsonData.city.id}</Text>
<ListView
dataSource={this.state.jsonData.list}
renderRow={(rowData) => <Text>{rowData.dt}</Text>}
/>
</View>
</View>
);
} else {
return (
<View style={styles.container}>
<ToolbarAndroid
style={styles.baseToolbar}
logo={require('./ic_launcher.png')}
title="Sunshine"
titleTextColor="red"/>
<View style={styles.singleviewcontainer}>
<Text>Loading...</Text>
</View>
</View>
);
}
}
getMoviesFromApiAsync() {
return fetch('http://api.openweathermap.org/data/2.5/forecast/daily?q=94043&mode=json&units=metric&cnt=14&APPID=18dcba27e5bca83fe4ec6b8fbeed7827')
.then((response) => response.json())
.then((responseJson) => {
this.setState({isLoading: false, jsonData: responseJson});
console.log(responseJson);
return responseJson;
})
.catch((error) => {
console.error(error);
});
}
}
AppRegistry.registerComponent('Sunshine', () => Sunshine);
What I think it should happen is that when an answer arrives from the server, the list is populated with it's result. But that's not what's going on. Intsead i get this error:
undefined is not an object (evaluating 'allRowIDs.length')
So what exactly am i doing wrong here?
You have to create a ListViewDataSource with the data list.
constructor (props) {
super(props)
this.dataSource = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2
})
}
componentDidMount () {
// You don't need to assign the return value to the state
this.getMoviesFromApiAsync()
}
render () {
// Use the dataSource
const rows = this.dataSource.cloneWithRows(this.state.jsonData.list || [])
...
return (
...
<ListView
dataSource={rows}
/>
)
}
Full docs here.