Can't access JSON data and print Begin and End only React Native - json

I'm trying to access to Begin and End inside JSON data but I can't. It just accesses and prints JSON data.
How can I print the Begin and End in separately FlatList?
Here is my code :
manage = date => {
this.setState({status: true})
this.setState({date:date})
const office_id=this.state.office_id;
const duration=this.state.duration;
const url='http://MyIP/api/timeApi';
axios.post(url,{office_id,date,duration})
.then(resp => this.setState({
testArray : JSON.stringify(resp.data),
}))
.catch(e)
{
alert(e);
}}
testFunction = () => {
var x = this.state.testArray;
return(
<Text>{x}</Text>
)
}
<DatePicker
date={this.state.date}
onDateChange={this.manage.bind(this) } />
in return
{
this.state.status ? <View>
<FlatList
data={this.state.testArray}
renderItem={this.testFunction}
/>
</View> : null
}
and here is my result

you need something like this , try to change it based on your code
import React, { Component } from 'react';
import {Text, View, FlatList ,Button} from 'react-native';
export default class Test extends Component {
constructor() {
super();
this.state = {
data: ['one', 'two', 'three', 'four', 'five'],
}
}
_keyExtractor = (item, index) => index.toString();
_renderItem = ({ item }) => (
<View>
<Text>{item}</Text>
</View>
);
manage = () => {
var x = this.firstAndLast(this.state.data);
this.setState({
data : x
})
}
firstAndLast(myArray) {
var firstItem = myArray[0];
var lastItem = myArray[myArray.length-1];
var newArray = [];
newArray.push(firstItem);
newArray.push(lastItem);
return newArray;
}
render() {
return (
<View>
<FlatList
data={this.state.data}
extraData={this.state}
keyExtractor={this._keyExtractor}
renderItem={this._renderItem}
/>
<Button title="click" onPress={() => this.manage()} />
</View>
);
}
}

Related

Objects are not valid as a React child (found: object with keys { my keys })

when I submit my form with the const onSubmit, I fetch data. If the submit form is ok, I want to extract the data I get from my api. So I use, setState reponse : my data, and then I want to pass this data (reponse) to the component SingleLayout.
But it doesn't work. I get this error : [Error: Objects are not valid as a React child (found: object with keys {ID, Post Title, post_date, Prix, Surface, Ville, Category, featured_image, mandats_signes, date_de_signature_du_compromis}). If you meant to render a collection of children, use an array instead.]
Here the code :
export default class QueryChild extends Component {
state = {
username: "",
password: "",
isLogged: null,
email: "",
reponse: '',
id: 4577
}
constructor(props) {
super(props);
this.render();
}
onSubmit = async() => {
const fetchValue = 'myAPI/suivi-dossier?' + 'username=' + this.state.username + '&password=' + this.state.password + '&id=' + this.state.id
try {
await fetch(fetchValue, {
method: 'GET'
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.success === true) {
// I want to extract this :
this.setState({ reponse: responseJson.message })
this.setState({ isLogged: true })
} else {
this.setState({reponse : responseJson.message });
console.log(this.state.reponse)
}
// this.setState({
// data: responseJson
// })
})
.catch((error) => {
console.error(error);
});
} catch (err) {
console.log(err)
}
}
render() {
if(this.state.isLogged === true) {
// when user is Logged, I want to pass this.state.reponse to my component SingleLayout
// but I get the error : [Error: Objects are not valid as a React child
// (found: object with keys {ID, Post Title, post_date, Prix, Surface, Ville,
// Category, featured_image, mandats_signes, date_de_signature_du_compromis}). If you
// meant to render a collection of children, use an array instead.]
const SingleComponent = this.state.reponse.map(message => <SingleLayout key={message.ID} table={message}/> )
return (
<SafeAreaView>
{SingleComponent}
</SafeAreaView>
);
} else {
return (
<View style={styles.container}>
<ScrollView>
<ImageBackground source={image} resizeMode="cover" style={styles.image}>
<Spacer taille={70} />
<View style={styles.content}>
<Image
style={styles.imgLogo}
source={require('../../logo.png')}
/>
<Text style={styles.logo}>Pour des raisons de sécurité, veuillez entrer vos Identifiants</Text>
<View style={styles.inputContainer}>
<Text style={styles.textBasique}>{this.state.reponse}</Text>
<TextInput
placeholder='Identifiant ou adresse email'
style={styles.input}
value={this.state.username}
onChangeText={val => this.setState({ username: val})}
/>
<TextInput
placeholder='Mot de passe'
style={styles.input}
value={this.state.password}
secureTextEntry= {true}
onChangeText={val => this.setState({ password: val})}
/>
<Spacer taille={10} />
<Button title='Se Connecter' onPress={this.onSubmit}/>
<Spacer taille={10} />
</View>
</View>
<Spacer taille={200} />
</ImageBackground>
</ScrollView>
</View>
)
}
}
}
Thank you.
The response that comes from the server is an object. Since the "map" function only works with an array so, if you want to run this code you've to wrap "responseJson.message" into the array.
if(responseJson.success === true) {
this.setState({ reponse: [responseJson.message] })
this.setState({ isLogged: true })
}
Yes I get similar error after applying the solution because I found that the error comes from the setState reponse. So I added JSON.stringify and now the error is gone.
The code of Single Layout :
const SingleLayout = (props) => {
let id = props.id
let table = props.table
console.log(table)
const { colors } = useTheme();
return (
<View style={[styles.container, {backgroundColor: colors.background}]}>
<Text>Bravo</Text>
</View>
)
}
Now with the solution : const SingleComponent = Object.keys(this.state.reponse).map(key => )
it works but it send caracters one by one
SO I finally solved my problem :
the code i change :
QueryChild.tsx :
if(responseJson.success === true) {
//here :
this.setState({ reponse: JSON.stringify(responseJson.message) })
this.setState({ isLogged: true })
and I directly return SingleLayout like that :
return (
<SafeAreaView>
<SingleLayout table={this.state.reponse} />
</SafeAreaView>
Now I can access this.state.reponse into my SingleLayout :
const SingleLayout = (props) => {
let id = props.id
let table = props.table
const myObj = JSON.parse(table);
console.log(myObj[0].mandats_signes)
console.log(myObj[0].ID)
console.log(myObj[0].Category)
//etc...
const { colors } = useTheme();
return (
<View style={[styles.container, {backgroundColor: colors.background}]}>
<Text>Bravo</Text>
</View>
)
}
it's not a good practice to pass JSON and then parse.
I solved it and here is the link with the same solution that I presented to you:
https://codesandbox.io/s/peaceful-bouman-qyi5y?file=/src/App.js

React Native Download JSON but not displaying in Flatlist

I am trying to download the JSON. React Native is downloading the json but I am not sure why Flatlist is not displaying the items. If I change the data={dummyData} in flatlist to data={MyList} then, the flatlist is able to display.
let viewableItemsChanged = null;
const dummyData = GrabData('http://hunterdata.serveblog.net/10record.json');
const MyList = [
{"id":"0","title":"MyBook0","url":"URLBook-0","image":"image-0" },
{"id":"1","title":"MyBook1","url":"URLBook-1","image":"image-1" },
{"id":"2","title":"MyBook2","url":"URLBook-2","image":"image-2" },
{"id":"3","title":"MyBook3","url":"URLBook-3","image":"image-3" },
{"id":"4","title":"MyBook4","url":"URLBook-4","image":"image-4" },
{"id":"5","title":"MyBook5","url":"URLBook-5","image":"image-5" }];
async function GrabData(TheURL) {
let abc = [];
try {
let response = await fetch(TheURL, {headers: {'Cache-Control' : 'no-cache'}});
let responseJson = await response.json();
console.log(responseJson);
return responseJson;
} catch (error) {
console.error(error);
}
}
const renderItem = ({item}) => {
return <View><Text>{item.title}</Text></View>
}
const List = () => {
return (
<FlatList
style={styles.list}
data={dummyData}
renderItem={renderItem}
/>
)
};
there is an issue with your code. you are calling the async function without await keyword. so it returns undefine response like this. {"_U": 0, "_V": 0, "_W": null, "_X": null}
Please Try this solution.
import React, { useEffect , useState } from 'react';
import { SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
const Item = ({ title }) => (
<View style={styles.item}>
<Text style={styles.title}>{title}</Text>
</View>
);
const App = () => {
const [data, setData] = useState([])
useEffect(() => {
apicall();
},[])
const apicall = async () => {
let dd = await GrabData("http://hunterdata.serveblog.net/10record.json");
setData(dd)
}
const GrabData = async (TheURL) => {
try {
let response = await fetch(TheURL, {headers: {'Cache-Control' : 'no-cache'}});
let responseJson = await response.json();
return responseJson;
} catch (error) {
console.error(error);
}
}
const renderItem = ({ item }) => (
<Item title={item?.title} />
);
return (
<SafeAreaView style={styles.container}>
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={item => item?.id}
/>
</SafeAreaView>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: StatusBar.currentHeight || 0,
},
item: {
backgroundColor: '#f9c2ff',
padding: 20,
marginVertical: 8,
marginHorizontal: 16,
},
title: {
fontSize: 32,
},
});
export default App;
You should activate the functions in componentDidMount also try states instead of const

React Native Download multiple JSON and combine

I am trying to download multiple JSON and combine them together in the variable and display them in a flatlist. But I am only seeing contents from only 1 JSON. How do we do multiple download and combine the result ? Is there a better way to do this ? Am I downloading it the correct way ?
export default class CategoryScreen extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
dataSource: [],
AllNews: [],
}
}
componentDidMount(){
this.GrabData('http://hunterdata.serveblog.net/t-computerworld.json');
this.GrabData('http://hunterdata.serveblog.net/t-thestar.json');
}
async GrabData(TheURL) {
let tmpData = [];
try{
const response = await fetch(TheURL, {headers: {'Cache-Control' : 'no-cache'}});
const data = await response.json();
tmpData = data;
if ((this.state.dataSource.length) = 0) {
this.setState({ dataSource: tmpData });
} else {
let tmpData1 = this.state.dataSource;
tmpData = [...tmpData1, ...data];
this.setState({ isLoading: false, dataSource: tmpData})
}
} catch (error) {
console.error(error);
}
}
render() {
if (this.state.isLoading) {
return (
<View>
<ActivityIndicator />
</View>
)
} else {
let mydata = this.state.dataSource;
return (
<View style={styles.container}>
<FlatList
data={mydata}
renderItem={({item}) => <Text style={styles.text}>{item.title}</Text>}
/>
</View>
);
}
}
}
if ((this.state.dataSource.length) = 0) {
Should be
if ((this.state.dataSource.length) === 0) {
You are so right. Thank you. This solved my issue.
if ((this.state.dataSource.length) === 0) {

How to load data onto a React State from an API instead of local json file?

So as part of my project I'm trying to ammend this boilerplate of React-Pdf-Highlighter to accept pdf highlights from flask-api instead of a local file( the example came with a local/json import) ..
I have tried to check with console.log the fetch is not the problem, but I feel for somereason the 'testHighlights' state is not what it should be .
<<App.js>>
// #flow
/* eslint import/no-webpack-loader-syntax: 0 */
import React, { Component } from "react";
import PDFWorker from "worker-loader!pdfjs-dist/lib/pdf.worker";
import {
PdfLoader,
PdfHighlighter,
Tip,
Highlight,
Popup,
AreaHighlight,
setPdfWorker
} from "react-pdf-highlighter";
import Spinner from "./Spinner";
import Sidebar from "./Sidebar";
import testHighlights from "./test-highlights";
import type {
T_Highlight,
T_NewHighlight
} from "react-pdf-highlighter/src/types";
import "./style/App.css";
setPdfWorker(PDFWorker);
type Props = {};
type State = {
url: string,
highlights: Array<T_Highlight>
};
const getNextId = () => String(Math.random()).slice(2);
const parseIdFromHash = () =>
document.location.hash.slice("#highlight-".length);
const resetHash = () => {
document.location.hash = "";
};
const HighlightPopup = ({ comment }) =>
comment.text ? (
<div className="Highlight__popup">
{comment.emoji} {comment.text}
</div>
) : null;
const PRIMARY_PDF_URL = "https://arxiv.org/pdf/1708.08021.pdf";
const SECONDARY_PDF_URL = "https://arxiv.org/pdf/1604.02480.pdf";
const searchParams = new URLSearchParams(document.location.search);
const initialUrl = searchParams.get("url") || PRIMARY_PDF_URL;
class App extends Component<Props, State> {
state = {
url: initialUrl,
highlights: testHighlights[initialUrl]
? [...testHighlights[initialUrl]]
: []
};
state: State;
resetHighlights = () => {
this.setState({
highlights: []
});
};
toggleDocument = () => {
const newUrl =
this.state.url === PRIMARY_PDF_URL ? SECONDARY_PDF_URL : PRIMARY_PDF_URL;
this.setState({
url: newUrl,
highlights: testHighlights[newUrl] ? [...testHighlights[newUrl]] : []
});
};
scrollViewerTo = (highlight: any) => {};
scrollToHighlightFromHash = () => {
const highlight = this.getHighlightById(parseIdFromHash());
if (highlight) {
this.scrollViewerTo(highlight);
}
};
componentDidMount() {
window.addEventListener(
"hashchange",
this.scrollToHighlightFromHash,
false
);
}
getHighlightById(id: string) {
const { highlights } = this.state;
return highlights.find(highlight => highlight.id === id);
}
addHighlight(highlight: T_NewHighlight) {
const { highlights } = this.state;
console.log("Saving highlight", highlight);
this.setState({
highlights: [{ ...highlight, id: getNextId() }, ...highlights]
});
}
updateHighlight(highlightId: string, position: Object, content: Object) {
console.log("Updating highlight", highlightId, position, content);
this.setState({
highlights: this.state.highlights.map(h => {
const {
id,
position: originalPosition,
content: originalContent,
...rest
} = h;
return id === highlightId
? {
id,
position: { ...originalPosition, ...position },
content: { ...originalContent, ...content },
...rest
}
: h;
})
});
}
render() {
const { url, highlights } = this.state;
return (
<div className="App" style={{ display: "flex", height: "100vh" }}>
<Sidebar
highlights={highlights}
resetHighlights={this.resetHighlights}
toggleDocument={this.toggleDocument}
/>
<div
style={{
height: "100vh",
width: "75vw",
position: "relative"
}}
>
<PdfLoader url={url} beforeLoad={<Spinner />}>
{pdfDocument => (
<PdfHighlighter
pdfDocument={pdfDocument}
enableAreaSelection={event => event.altKey}
onScrollChange={resetHash}
// pdfScaleValue="page-width"
scrollRef={scrollTo => {
this.scrollViewerTo = scrollTo;
this.scrollToHighlightFromHash();
}}
onSelectionFinished={(
position,
content,
hideTipAndSelection,
transformSelection
) => (
<Tip
onOpen={transformSelection}
onConfirm={comment => {
this.addHighlight({ content, position, comment });
hideTipAndSelection();
}}
/>
)}
highlightTransform={(
highlight,
index,
setTip,
hideTip,
viewportToScaled,
screenshot,
isScrolledTo
) => {
const isTextHighlight = !Boolean(
highlight.content && highlight.content.image
);
const component = isTextHighlight ? (
<Highlight
isScrolledTo={isScrolledTo}
position={highlight.position}
comment={highlight.comment}
/>
) : (
<AreaHighlight
highlight={highlight}
onChange={boundingRect => {
this.updateHighlight(
highlight.id,
{ boundingRect: viewportToScaled(boundingRect) },
{ image: screenshot(boundingRect) }
);
}}
/>
);
return (
<Popup
popupContent={<HighlightPopup {...highlight} />}
onMouseOver={popupContent =>
setTip(highlight, highlight => popupContent)
}
onMouseOut={hideTip}
key={index}
children={component}
/>
);
}}
highlights={highlights}
/>
)}
</PdfLoader>
</div>
</div>
);
}
}
export default App;
<<test-highlights.js >>
const testHighlights =async () => {
const res= await fetch('http://127.0.0.1:5000/jsonapi')
const data =await res.json()
console.log(data)
this.state.testHighlights = data
return testHighlights;
}
export default testHighlights;
You can't assign state like this
this.state.testHighlights = data
You must use this.setState function to do it
this.setState({ testHighlights: data });
That is why your testHighlights state isn't what you was expected

Not getting any return value from function [React Native]

I have this menu where I filter the button when user is logged and I'm accessing a function from a separate file to check out if user is logged or not.
From menu
import { IsLogged } from '../GlobalFunctions';
const SubDrawer1 = ({ data, onChange }) => (
<View>
{
IsLogged() ? (
<View>
<TouchableOpacity onPress={()=>{onChange('LogoutScreen')}}>
<Text>Logout</Text>
</TouchableOpacity>
</View>
) : (<View />)
}
</View>
);
export default SubDrawer1;
From GlobalFunctions
export function IsLogged(){
AsyncStorage.getItem('userId').then((userId) => {
return userId ? true : false
})
}
From menu I call out IsLogged() function but the value is undefined when I console.log it. It supposed to return either true or false.
You are trying to call a async function, so you need to add some extra code. Try the following.
SubDrawer1
import { Text, View, TouchableOpacity } from "react-native";
import React, { Component } from "react";
import { IsLogged } from "../GlobalFunctions";
const SubDrawer1 = async ({ data, onChange }) => {
const status = await IsLogged();
if (status === true) {
return (
<View>
<View>
<TouchableOpacity
onPress={() => {
onChange("LogoutScreen");
}}
>
<Text>Logout</Text>
</TouchableOpacity>
</View>
</View>
);
} else {
return (
<View>
<View />
</View>
);
}
};
export default SubDrawer1;
'IsLogged()' Global function
export function async IsLogged(){
let userId = await AsyncStorage.getItem('userId');
return userId ? true : false
}
'SubDrawer1' using class
...
import SubDrawer1 from "./SubDrawer1"; // import your 'SubDrawer1' component
var subDrawer1Component; // declare a variable for your rendering component
//Your main class
export default class ClassName extends Component<Props> {
componentDidMount() {
this.getComponentInfo(); //Call this method to get function
}
getComponentInfo = async () => {
subDrawer1Component = await SubDrawer1();// Will take the component
this.setState({ isDataGet: true });
};
render() {
return (
...
{subDrawer1Component}
...
);
}
}
...
because AsyncStorage will take some time, and before that function completes its execution. (Because everything in JS is asynchronous)
So just make it wait until it finishes getting an item,
export function async IsLogged(){
let userId = await AsyncStorage.getItem('userId');
return userId ? true : false
}