I am creating an app using expo. You can check the snack here
I am also giving the code here:
import React, {Component} from 'react';
import { ActivityIndicator, Text, View, StyleSheet, FlatList, Alert, TouchableOpacity } from 'react-native';
import {Avatar, Card, Button, Divider, ListItem, Image} from 'react-native-elements';
import Icon from 'react-native-vector-icons/FontAwesome';
import Constants from 'expo-constants';
import HTML from 'react-native-render-html';
import UserAvatar from 'react-native-user-avatar';
import { StackNavigator } from 'react-navigation';
import { createAppContainer} from 'react-navigation';
import { createStackNavigator } from 'react-navigation-stack';
class HomeScreen extends React.Component{
static navigationOptions =
{
title: '',
};
constructor(props){
super(props);
this.state = {
Loading : true,
data : []
}
}
fetchLeash(){
fetch('https://lishup.com/app/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data: responseJson, Loading:false });
}).catch((error) => {
Alert.alert('error!');
});
}
fetchImage(getimg){
fetch('https://lishup.com/app/fetch-image.php', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
image: getimg
})
}).then((response) => response.json())
.then((responseJson) => {
return (<Text>responseJson.url</Text>);
}).catch((error) => {
Alert.alert('error');
});
}
componentDidMount(){
this.fetchLeash();
}
renderLeash = ({ item }) => (
<View>
<Card style={{ height:100, justifyContent: 'center', alignItems: 'center' }}>
<ListItem
leftAvatar={{
title: item.user,
source: { uri: item.userpic },
}}
title={item.user}
subtitle={item.time}
chevron
/>
<Divider style={{margin:5, backgroundColor:'white'}} />
<HTML html={item.text} />
{this.fetchImage(item.images)}
</Card>
</View>
)
render(){
if(this.state.Loading == true){
return(
<ActivityIndicator size="large" style={{marginTop:100}} color="#0000ff" />
);
}else{
return(
<View>
<FlatList style={{width:400}}
data={this.state.data}
renderItem={this.renderLeash} />
</View>
);
}
}
}
const styles = StyleSheet.create({
});
const RootStack = createStackNavigator(
{
Home: { screen: HomeScreen },
},
{
initialRouteName: 'Home',
}
);
export default createAppContainer(RootStack);
If you run the snack in your device, you will see that the posts(fetchLeash() function) is working fine. But the fetchImage() is returning nothing.
My fetch-image.php file is here:
<?php
// Importing DBConfig.php file.
include 'DB.php';
header('Content-Type: application/json');
// Creating connection.
$con = mysqli_connect($HostName,$HostUser,$HostPass,$DatabaseName);
// Getting the received JSON into $json variable.
$json = file_get_contents('php://input');
// decoding the received JSON and store into $obj variable.
$obj = json_decode($json,true);
// Populate User email from JSON $obj array and store into $email.
$image = $obj['image'];
if($image == "") {
$blank[] = array("url"=>"");
echo json_encode($blank);
}else{
//query to get image url with the code received
$Sql_Query = "SELECT * FROM `leash_img` WHERE `pid`= '".$image."' ";
// Executing SQL Query.
$check = mysqli_query($con,$Sql_Query);
if($check){
while($row=mysqli_fetch_assoc($check)){
$SuccessLoginMsg[] = array("url"=> $row['image']);
}
// Converting the message into JSON format.
$SuccessLoginJson = json_encode($SuccessLoginMsg);
echo $SuccessLoginJson;
}
}
?>
This returns like the following:
[{"url":"link here"}]
The PHP file is working fine. But the react native fetchImage() is not working.
I am totally new to react native. So forgive my problems. I am just out of my ideas. Please help me.
You can't asynchronously render UI from the render function, you need to fetch the data outside it in one of the lifecycle functions and conditionally render UI while it is being fetched.
Once the data has been fetched you should go ahead and fetch the image urls. Use Promise.all and map each response item to a fetch request. This will allow all image url fetches to resolve asynchronously and maintain index order.
fetchLeash() {
fetch('https://lishup.com/app/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data: responseJson });
Promise.all(responseJson.map(({ images }) => this.fetchImage(images)))
.then((images) => {
this.setState({ imageUrls: images.map(url => ({ uri: url })) })
});
})
.catch((error) => {
Alert.alert('error!');
})
.finally(() => {
this.setState({ Loading: false });
});
}
The other important change is that the image response is an array of length 1, so need to access correctly.
fetchImage(image) {
return fetch('https://lishup.com/app/fetch-image.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ image }),
})
.then((response) => response.json())
.then((responseJson) => responseJson[0].url);
}
Now you can conditionally render an Image if the url at that index exists.
renderLeash = ({ item, index }) => (
<View>
<Card
style={{ height: 100, justifyContent: 'center', alignItems: 'center' }}>
<ListItem
leftAvatar={{
title: item.user,
source: { uri: item.userpic },
}}
title={item.user}
subtitle={item.time}
chevron
/>
<Divider style={{ margin: 5, backgroundColor: 'white' }} />
<HTML html={item.text} />
<Text>
{this.state.imageUrls[index] && this.state.imageUrls[index].uri}
</Text>
{this.state.imageUrls[index] && (
<Image
source={this.state.imageUrls[index]}
style={{ width: 100, height: 100 }}
PlaceholderContent={<ActivityIndicator />}
/>
)}
</Card>
</View>
);
Expo Snack
EDIT Allow display of all fetched image URLs. Instead of grabbing and returning just the first URL, return an array of URLs. Below I mapped the URLs to a new array before returning them, and these can be set directly in state now. Update the render function to use an additional guard (array length check) and render null if array doesn't exist. (Could also use another FlatList here if you wanted to)
fetchLeash() {
return fetch('https://lishup.com/app/')
.then((response) => response.json())
.then((responseJson) => {
this.setState({ data: responseJson });
Promise.all(
responseJson.map(({ images }) => this.fetchImage(images))
).then((imageUrls) => this.setState({ imageUrls }));
})
.catch((error) => {
Alert.alert('error!');
})
.finally(() => {
this.setState({ Loading: false });
});
}
fetchImage(image) {
return fetch('https://lishup.com/app/fetch-image.php', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ image }),
})
.then((response) => response.json())
.then((responseJson) =>
// Filter elements with empty string URLs, then app just the URL
responseJson.filter(({ url }) => url).map(({ url }) => url)
);
}
...
{this.state.imageUrls[index] && this.state.imageUrls[index].length
? this.state.imageUrls[index].map((uri) => (
<Image
source={{ uri }}
style={{ width: 100, height: 100 }}
PlaceholderContent={<ActivityIndicator />}
/>
))
: null}
Related
I wanted to show a list of data in my app, I already have backend API that can get the data from the server but when I trying to make it appear in my react native app, it wont appear. Below is the data that get from API
here is the code for show the data in a list view in react native apps
import React, { useState, useEffect,Component,onMount} from 'react';
import {View,Text, Button, StyleSheet,TextInput,ListView,ActivityIndicator,Platform} from 'react-native';
import {useNavigation} from'#react-navigation/native';
import {StatusBar} from'expo-status-bar';
export default function StopJob(){
const[isLoading,setIsLoading]=useState(true);
useEffect(()=>{
return fetch('http://localhost/api/findid.php',{
mode:'no-cors'
})
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2)=> r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson),
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
})
},[]);
const Showlist=(user,job,jobid,machinecode,startTime)=>{
this.props.navigation.navigate('Third', {
Userid : user,
Job : job,
JobId : jobid,
MachineCode : machinecode,
StartTime : startTime
});
}
const ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
if(isLoading)return(<View style={{flex: 1, paddingTop: 20}}><ActivityIndicator /> </View>);
return(
<View style={styles.MainContainer_For_Show_StudentList_Activity}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={ (rowData) => <Text style={styles.rowViewContainer}
onPress={this.Showlist.bind(
this, rowData.user,
rowData.job,
rowData.jobid,
rowData.machinecode,
rowData.startTime
)} >
{rowData.job}
</Text> }
/>
</View>
);
}
const styles = StyleSheet.create({
MainContainer_For_Show_StudentList_Activity :{
flex:1,
paddingTop: (Platform.OS == 'ios') ? 20 : 0,
marginLeft: 5,
marginRight: 5
},
rowViewContainer: {
fontSize: 20,
paddingRight: 10,
paddingTop: 10,
paddingBottom: 10,
}
});
the expected output will only show the job from the database, but for now the function did not show the list view the error shown Text strings must be rendered within a component.
I was referring this webpage to implement the code : https://reactnativecode.com/insert-update-display-delete-crud-operations/
on the example it show function well but when I try to implement it, it cant work :(
updated but still having same error
export default function StopJob(){
const[isLoading,setIsLoading]=useState(true);
const[dataSource,setdataSource]=useState();
useEffect(()=>{
return fetch('http://localhost/api/findid.php')
.then((response) => response.json())
.then((responseJson) => {
let ds = new FlatList.DataSource({rowHasChanged: (r1, r2)=> r1 !== r2});
setIsLoading(false)
setdataSource(ds.cloneWithRows(responseJson))
})
.catch((error) => {
console.error(error);
})
},[]);
const Showlist=(user,job,jobid,machinecode,startTime)=>{
this.props.navigation.navigate('', {
Userid : user,
Job : job,
JobId : jobid,
MachineCode : machinecode,
StartTime : startTime
});
}
const ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
if(isLoading)return(<View style={{flex: 1, paddingTop: 20}}><ActivityIndicator /> </View>);
return(
<View style={styles.MainContainer_For_Show_StudentList_Activity}>
<FlatList
dataSource={dataSource}
keyExtractor={item=>item.user}
ItemSeparatorComponent= {ListViewItemSeparator()}
renderItem={ (item) => <Text style={styles.rowViewContainer}>{item.job}</Text> }
/>
</View>
);
}
Ok here are the steps to follow:
Use flatlist
Your data source should be a regular array. So, you can use the response from your api as it is.
renderRow should change as renderItem
renderSeparator should change as ItemSeparatorComponent
here is the final form:
const[isLoading,setIsLoading]=useState(true);
const [data, setData]=useState([]);
.......
fetch('http://localhost/api/findid.php',{
mode:'no-cors'
})
.then((response) => response.json())
.then((responseJson) => {
//you can't use setState inside function components. :)
setData(responseJson);
setLoading(false);
})
.catch((error) => {
console.error(error);
})
.......
<FlatList
data={data}
keyExtractor={item => item.jobid} //it should be unique. change it
renderItem={({item}) => <Text>{item.job}</Text>}
/>
This should solve your issue for now but keep in mind these too:
Looks like you don't know differences between class components and function components. Do your research
Flatlist has it's own performance configurations. Research and implement them.
I want to display a list of places from a online json url.
import React, { Component } from "react";
import {
View,
StyleSheet,
Dimensions,
Image,
StatusBar,
TextInput,
TouchableOpacity,
Text,
Button,
Platform,
Alert,
FlatList,
ActivityIndicator,
} from "react-native";
let url = "https://cz2006api.herokuapp.com/api/getAll";
let url2 = "";
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: null,
};
}
componentDidMount() {
return fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
let hospitals = this.state.dataSource.map((val, key) => {
return (
<View key={key} style={styles.item}>
<Text>{val.name}</Text>
</View>
);
});
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{hospitals}
</View>
);
}
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
item: {
flex: 1,
alignSelf: "stretch",
margin: 10,
alignItems: "center",
justifyContent: "center",
borderBottomWidth: 1,
borderBottomColor: "#eee",
},
});
Unfortunately when i tried to run this via expo cli I got an error, saying undefined is not an object
enter image description here
Can anyone help me pls!!! I would just like to have a list of hospitals which are scrollable. Thank you!
The URL of the Json is here: https://cz2006api.herokuapp.com/api/getAll
Simply change your initial state to something like this
this.state = {
isLoading: true,
dataSource: [], // <-- here
};
Your problem is you're using dataSource.map but during api calling your dataSource still stay null until it get its response, and null object have no attribute map. That's the cause of your problem.
remove the return in componentDidMount:
componentDidMount() {
fetch("https://cz2006api.herokuapp.com/api/getAll")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
dataSource: responseJson.data.data,
isLoading: false,
});
})
.catch((error) => {
console.log(error);
});
}
I agree with #Nguyễn's suggestion that your initial state should be an array. However the root of the issue seems to be getting the right properties off off your JSON response.
First, you want responseJson.data instead of responseJson.data.data. That gives me an array and shows a long list but the titles are all blank. That's because your response has Name as an uppercase property but you are accessing name. So you need to change that as well.
export default class ClinicComponent extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
};
}
componentDidMount() {
return fetch('https://cz2006api.herokuapp.com/api/getAll')
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson.data,
});
})
.catch((error) => {
console.log(error);
});
}
render() {
//console.log(this.state.dataSource?.[0]);
if (this.state.isLoading) {
return (
<View style={styles.container}>
<ActivityIndicator />
</View>
);
} else {
return (
<View style={styles.item}>
{/* <Text>Content Loaded</Text> */}
{this.state.dataSource.map((val, key) => (
<View key={val._id} style={styles.item}>
<Text>{val.Name}</Text>
</View>
))}
</View>
);
}
}
}
You are fetching a huge amount of data and you probably want some sort of pagination with infinite scrolling. It is extremely slow to load due to the huge payload that we are fetching.
You also have double-escape problem in the JSON response inside the geocodingData section. You want to return this data as an object but it is an escaped string with lots of \" instead.
I have created a Banner Component in React Native and now im trying to add data from a function (seperate .js file) in this component. I want to fetch the data on the inital load from my Home Screen but i dont know how to pass the data from my function. I hope you can help me.
This is my code:
home.js
export function HomeScreen() {
{/*This will cause an error*/}
const [item, setItem] = React.useState([]);
React.useEffect(() => {
{/*Function where i fetch my Data from API */}
getbannerdata().then(res => {
setItem(res)
})
console.log(item)
}, [])
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
{/*Banner Component with Data param*/}
<Banner data={item} />
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
My function:
bannerdata.js
export const getbannerdata = () => {
const [data, setData] = React.useState([])
console.log('Test')
fetch('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then(res => res.json())
.then(res => {
console.log(res)
setData(res)
})
.catch(error => console.log(error));
return data;
};
I hope you can help me.
You should use useState in your component only not in the function where you fetch data.
bannerdata.js
export const getbannerdata = () => {
return fetch('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
});
};
home.js
import { getbannerdata } from './bannerdata'; //import getbannerdata function and you should provide the path of bannerdata.js
export function HomeScreen() {
const [item, setItem] = React.useState([]);
React.useEffect(() => {
{/*Function where i fetch my Data from API */}
getbannerdata()
.then(res => res.json())
.then(res => {
console.log(res)
setItem(res);
});
.catch(error => console.log(error));
}, []);
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
{/*Banner Component with Data param*/}
<Banner data={item} />
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
Thank you for your help.
This is my final solution.
Its a little bit different but now it works as expected
bannerdata.js
import * as React from 'react';
function getbannerdata(){
return fetch ('http://192.168.178.46:8000/intranet/messages/', {
method: 'GET',
headers: {
'Content-Type': 'application/json',
},
})
.then((res) => res.json())
.then((resData) => {
return resData;
})
.catch(error => console.log(error))
};
export { getbannerdata }
home.js
import {getbannerdata} from './home/bannerdata.js';
export function HomeScreen() {
const [item, setItem] = React.useState([]);
React.useEffect(() => {
getbannerdata()
.then(res => setItem(res))
}, []);
return (
<SafeAreaProvider>
<SafeAreaView style={style.container}>
<View>
{/*Banner Component with Data param*/}
<Banner data={item} />
<Text>Home</Text>
</View>
</SafeAreaView>
</SafeAreaProvider>
);
}
So I am making a ToDo app but so far I can just create a task, or delete it. Right now I am trying to make another feature where I can edit the specific task by clicking the edit button and then it will change the task into an input area where i can edit the task name. Can someone help me with this? How it looks right now is displayed below.
My Code right now is below:
import React, { Component } from 'react';
import axios from "axios";
export default class TaskInput extends Component {
constructor(props) {
super(props)
this.state = {
task: " ",
allTasks: [],
strikeThrough: {textDecoration:""}
}
}
changeHandler = (event) => {
console.log(event.target.value)
this.setState({
task: event.target.value,
})
}
handleStrikethrough = (completed, id) => {
// !completed ? this.setState({strikeThrough:{textDecoration: "line-through"}}) : this.setState({strikeThrough:{textDecoration:""}})
// if (!completed) {
// console.log("not completed", !completed)
// this.setState({strikeThrough:{textDecoration: "line-through"}});
// axios.put("/api/task", {
// completed: !completed
// }, id).then(response => console.log(response))
// } else {
// this.setState({strikeThrough:{textDecoration:""}})
// axios.put("/api/task", {
// completed: !completed
// }, id).then(response => console.log(response))
// }
}
handleDelete = (taskId) => {
axios.delete("/api/task/" + taskId).then(data => {
console.log("You deleted the task with an id of ", data)
})
window.location.reload();
}
handleTaskEdit = () => {
console.log("edit button worked")
}
submitHandler = (event) => {
event.preventDefault() //to prevent page refresh
console.log()
fetch("/api/task", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify(this.state),
})
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.log(err))
this.setState({
task: ""
})
window.location.reload()
}
componentDidMount() {
console.log("component did mount")
const self = this;
axios.get("/api/tasks").then(function (data) {
self.setState({
allTasks: data.data
})
// console.log(self.state.allTasks[0].task)
})
}
render() {
const {strikeThrough, task, allTasks} = this.state; //destructuring the state
return (
<div>
<form onSubmit={this.submitHandler} >
<label style={{ margin: "5px 0px" }}>Create a Task:</label>
<input value={this.state.task} onChange={this.changeHandler} style={{ width: "100%" }}></input>
<input style={{ padding: "5px", marginTop: "5px" }} type="submit"></input>
</form>
<hr></hr>
<br></br>
<ul>
{this.state.allTasks.map(task => (
<li style={strikeThrough} onClick={()=>this.handleStrikethrough(task.completed, task.id)} className="tasks">{task.task}
<button onClick = {() => this.handleDelete(task.id)}>x</button>
<button onClick={this.handleTaskEdit}>edit</button>
</li>
)
)}
</ul>
</div>
)
}
}
You could set task ID on its corresponding Edit button, then when clicking Edit button get the task using ID and sending that task to an edit component.
First of all handleTaskEdit, here you set task name to the task property and set ID of editable task:
handleTaskEdit = id =>
this.setState({ task: this.state.allTasks.find(el => el.id === id).task })
secondly, create two new methods, createTask and updateTask:
createTask = () => {
fetch("/api/task", {
method: "POST",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({task: this.state.task}),
})
.then(res => res.json())
.then(data => this.setState({
task: '',
allTasks: [...this.state.allTasks, data]}))
.catch(err => console.log(err))
}
updateTask = () => {
fetch("/api/task", {
method: "PATCH",
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json'
},
body: JSON.stringify({task: this.state.task, id: this.state.editableTaskId}),
})
.then(res => res.json())
.then(data => this.setState({
task: '',
editableTaskId: null,
allTasks: this.state.allTasks.map(el =>
el.id === data.id ? data : el)})) // Or take new name and id from state
.catch(err => console.log(err))
}
and finally you need to update submitHandler and handleDelete:
submitHandler = () => {
if (this.state.editableTaskId) {
this.updateTask();
} else {
this.createTask()
}
}
handleDelete = (taskId) => {
axios.delete("/api/task/" + taskId).then(data => {
this.setState({allTasks: this.state.allTasks.filter(el =>
el.id !== data.id
)})
})
}
Here's the approach:
Have a state variable called editTaskID and keep the default value as null. On the edit button set the functionality of handleTaskEdit in such a way that it sets the editTaskID to that particular task ID on which edit button was clicked.
In the map function where you are rendering the list items for tasks, add a condition such as:
{this.state.allTasks.map(task =>
(
<li style={strikeThrough}
onClick={()=>this.handleStrikethrough(task.completed, task.id)}
className="tasks">
{
this.editTaskID
?<input
value={this.state.editTaskName}
/*supposing editTaskName to be state variable that stores
the edit textfield content.*/
onChange={this.changeEditHandler} style={{ width: "80%" }}>
</input>
:task.task
}
<button onClick = {() => this.handleDelete(task.id)}>x</button>
<button onClick={this.handleTaskEdit}>edit</button>
</li>
)
)
}
This will now check the condition whether the editTaskID has been set to null or not while rendering. In case if it is null, all your tasks will come as a plain text else it will come in form of a text box. You can also add the value to the edit task input field with the help of allTasks[editTaskID].
On the handleTaskEdit function of the edit button, make sure to set the allTasks[editTaskID] to the value editTaskName and also to set the state variable editTaskID to null.
Call the necessary backend endpoint to reflect the changes in your database as well.
I hope it helps. Thanks.
im new to react native and i have been able to fetch json data from server successfully. how do i pass the object into an array and render in my component. Here is my code
i've tried iterating over the object using .map() and i get "undefined is not a function". Ive also tried to convert the object into an array using Object.values and i get error "value for message cannot be cast from readablenativearray to string"
constructor(props) {
super(props);
//useraccountdetails will contain the object from the server
this.state = {
useraccountdetails: [],
}
this.loaduser_account_details= this.loaduser_account_details.bind(this)
}
componentWillMount() {
//this function will fetch the data from the server
this.loaduser_account_details()
}
loaduser_account_details() {
fetch('http://10.162.101.247/camfilaapiv2/commands/loggedin_user_account_details.php', {
method: 'POST',
headers: {
'Accept': 'text/plain',
'Content-Type': 'text/plain',
},
body: JSON.stringify({
globaluseridDB: modulevariables.globaluserid,
})
}).then((response) => response.text())
.then((responseJson) => {
var jsonconvertedrows = JSON.parse(responseJson);
var finaldata = JSON.stringify(jsonconvertedrows)
this.setState({ useraccountdetails: finaldata });
Alert.alert("User details", this.state.useraccountdetails)
}).catch((error) => {
console.error(error);
})
}
//alert(this.state.useraccountdetails) gives me this [{"user_id":"107","username":"sam","year":"6"}]
render(){
return (
/**page setup */
<View style={{ backgroundColor: '#203546', flex: 1, flexDirection: 'column' }}>
{/**body */}
<Grid>
{
this.state.useraccountdetails.map((count)=>{
<Text>{count.username}</Text>
})
}
</Grid>
</View>
)
}
It looks like it is because you are iterating over a string in your render. this.state.useraccountdetails is a string once your response is successful as you are setting it as the result stringified. To correct this all you will need to do is correct your setState to
this.setState({ useraccountdetails: jsonconvertedrows });
Can you try the following code?
constructor(props) {
super(props);
//useraccountdetails will contain the object from the server
this.state = {
useraccountdetails: [],
}
this.loaduser_account_details= this.loaduser_account_details.bind(this)
}
componentWillMount() {
//this function will fetch the data from the server
this.loaduser_account_details()
}
loaduser_account_details() {
fetch('http://10.162.101.247/camfilaapiv2/commands/loggedin_user_account_details.php', {
method: 'POST',
headers: {
'Accept': 'text/plain',
'Content-Type': 'text/plain',
},
body: JSON.stringify({
globaluseridDB: modulevariables.globaluserid,
})
}).then((response) => response.json())
.then((responseJson) => {
//var jsonconvertedrows = JSON.parse(responseJson);
//var finaldata = JSON.stringify(jsonconvertedrows)
this.setState({ useraccountdetails: responseJson });
Alert.alert("User details", this.state.useraccountdetails)
}).catch((error) => {
console.error(error);
})
}
//alert(this.state.useraccountdetails) gives me this [{"user_id":"107","username":"sam","year":"6"}]
render(){
return (
/**page setup */
<View style={{ backgroundColor: '#203546', flex: 1, flexDirection: 'column' }}>
{/**body */}
<Grid>
{
return this.state.useraccountdetails.map((count)=>{
return(
<Text>{count.username}</Text>
)
})
}
</Grid>
</View>
)
}
You are try to change the response to 'text', please change it from response.text() to response.json()
Change this.setState({ useraccountdetails: Object.values(jsonconvertedrows) }); as shown in code and try it:
loaduser_account_details() {
fetch('http://10.162.101.247/camfilaapiv2/commands/loggedin_user_account_details.php', {
method: 'POST',
headers: {
'Accept': 'text/plain',
'Content-Type': 'text/plain',
},
body: JSON.stringify({
globaluseridDB: modulevariables.globaluserid,
})
}).then((response) => response.text())
.then((responseJson) => {
var jsonconvertedrows = JSON.parse(responseJson);
var finaldata = JSON.stringify(jsonconvertedrows)
this.setState({ useraccountdetails: Object.values(finaldata) });
Alert.alert("User details", this.state.useraccountdetails)
}).catch((error) => {
console.error(error);
})
}