React Native : render a fetched data structure - json

I am new to Javascript (NodeJS & JSON data structure) and React native, and I am trying to display some datas on the iOS screen test (react native). I did my best to understand but I am stuck.
I made a GET route on my Express app at /places on localhost:3000 :
router.get('/places', (req, res) => {
MongoClient.connect(url, function (err, db) {
if (err) {
console.log('Unable to connect to the mongoDB server. Error:', err);
} else {
console.log('Connection established to', url);
var colPlaces = db.collection('places');
colPlaces.find().toArray(function (err,result) {
if (err) {
res.send('error!');
} else if (result.length) {
res.send(result);
} else {
res.send('No entries');
}
})
db.close();
}});
})
It displays a data structure on my browser (seems to be an Array of JSON objects ?)
[
{"_id":"5894fdd694f5d015dc0962bc","name":"The good bar","city":"London"},
{"_id":"5894fdd694f5d015dc0962bd","name":"Alpha bar","city":"Paris"}
]
I am then trying to render it on my native react project :
constructor(props) {
super(props);
var datas = async function getDatas() {
try {
let response = await fetch('http://localhost:3000/places');
let responseJson = await response.json();
return responseJson;
} catch(error) {
console.error(error); }
}
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.state = {
dataSource: ds.cloneWithRows(datas())
};
}
render() {
return (
<View style={{flex: 1, paddingTop: 22}}>
<ListView
dataSource={this.state.dataSource}
renderRow={(rowData) => <Text>{rowData}</Text>}
/>
</View>
);
}
But all I got is two "0" on my screen.
Can someone help me to find out what is wrong ?
What is/are,
* "result" variable structure ? seems to be an array of JS objects.
* "response" and "responseJSON" variables ?
* "datas()" and dataSource type
Should I parse something ? I am a bit confuse. Thank you.

First, "data" is already plural, there is no "datas". :) Now back to your question, getData is async function, so you cannot just call getData() and expect it to return data immediately. In the constructor, set dataSource to empty list, then:
async function getData() {
try {
let response = await fetch('http://localhost:3000/places');
return response.json(); // this call is not async
} catch(error) {
console.error(error);
}
}
componentDidMount() {
let data = await this.getData();
const ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({dataSource: ds.cloneWithRows(data)});
}

Related

cloud function Not all code paths return a value still I am returning all values possible?

any idea why my cloud function is telling my that (Not all code paths return a value) I put a return on the promise at the end also on the if statement yet it is not working, I read about similar issues tried to solve according to them but I still missing part of the puzzle, the error started showing when I wrapped the whole thing with try-catch.
export const createClient = functions.https.onCall(async(data, context) => {
try {
const snapshotCheckBelong = await db.collection('data- main').doc(data.sharedId).get();
const getClient = snapshotCheckBelong.data() ? .clients.filter((el: any) => el.clientId === data.clientId);
const snapshotCheckExist = await db.collection('data-registered-clients').doc(data.sharedId).get();
const checkClient = snapshotCheckExist.data() ? .clients.filter((el: any) => el.clientId === data.clientId);
if (checkClient[0]) {
return {
result: 'Registered client already exisits.'
};
}
if (getClient[0] ? .clientId === data.clientId && checkClient.length === 0) {
const payload = {
user: 'client',
verifiedEmail: false,
createdAt: admin.firestore.Timestamp.now(),
};
let auth = admin
.auth()
.getUserByEmail(context.auth ? .token ? .email!)
.then((user) =>
admin.auth().setCustomUserClaims(user.uid, {
userType: 'client',
premiumUnitll: admin.firestore.Timestamp.fromDate(snapshotCheckBelong.data() ? .premiumUntill)
})
)
.catch((err: any) => {
console.log(err);
});
let setClientData = db
.collection('data-clients')
.doc(context.auth ? .uid!)
.set(payload)
.catch((err: any) => {
console.log(err);
});
let updateRegisteredClients = db
.collection('data-registered-clients')
.doc(data.sharedId)
.update({
clients: admin.firestore.FieldValue.arrayUnion({
clientAccount: context.auth ? .uid,
clientId: data.clientId,
trainerId: data.sharedId
})
})
.catch((err: any) => {
console.log(err);
});
return Promise.all([auth, setClientData, updateRegisteredClients]);
} else {
return null;
}
} catch {
(err: any) => {
console.log(err);
};
}
});
Your catch blocks are not returning anything. If you handle an error with catch, you have to determine what value gets returned to the caller.
I typically prefer sending the error back to the caller, as shown in the documentation on handling errors in callable cloud functions and on the calling client.

Getting empty {} from mysql table, on React and node.js

For some reason am getting empty object back from mysql table, the table is filled in with some vacation detail. And i want to display them with map in my react app.
On the client side am doing the request with useEffect state and axios.
useEffect(() => {
axios.get("http://localhost:3001/vacations")
.then((response) => {
let vacationsResponse = response.data;
dispatch({ type: ActionType.GetAllVacations, payload: vacationsResponse })
}).catch(err => {
console.log("Failed to get data" + err)
})
}, [dispatch])
this is the server side:
const vacationsControllers = require("./Controllers/vacationsControllers");
const cors = require("cors");
server.use(cors({ origin: "http://localhost:3000" }));
server.use("/users", usersController);
server.use("/vacations", vacationsControllers);
server.listen(3001, () => console.log("Listening on http://localhost:3001"));
this is the vacationsControllers folder:
router.get("/", async (request, response) => {
let vacationsData = request.body;
try {
await vacationsDao.getAllVacations(vacationsData);
response.json();
console.log(vacationsData) *get this empty in the node terminal*
} catch (e) {
console.error(e);
response.status(600).json();
}
});
module.exports = router;
The sql execute (the vacationDao folder):
let connection = require("./connection-wrapper");
async function getAllVacations(vacationsData) {
const sql = `SELECT * FROM current_deals`;
await connection.executeWithParameters(sql);
return vacationsData;
}
module.exports = {
getAllVacations,
};

ipfs.add is not working for ipfs client v44.3.0 how can I resolve this?

This is my code in App.js, and its always returning an "Unhandeled Rejection Type error saying that ipfs.add(...). then is not a function.
import React, { Component } from 'react';
import './App.css';
var ipfsAPI = require('ipfs-http-client')
var ipfs = ipfsAPI({host: 'localhost', port: '5001', protocol:'http'})
class App extends Component {
saveTestBlobOnIpfs = (blob) => {
return new Promise(function(resolve, reject) {
const descBuffer = Buffer.from(blob, 'utf-8');
ipfs.add(descBuffer).then((response) => {
console.log(response)
resolve(response[0].hash);
}).catch((err) => {
console.error(err)
reject(err);
})
})
}
render() {
return (
<div className="App">
<h1>IPFS Pool</h1>
<input
ref = "ipfs"
style = {{width: 200, height: 50}}/>
<button
onClick = {() => {
console.log("Upload Data to IPFS");
let content = this.refs.ipfs.value;
console.log(content);
this.saveTestBlobOnIpfs(content).then((hash) => {
console.log("Hash of uploaded data: " + hash)
});
}}
style = {{height: 50}}>Upload Data to IPFS</button>
</div>
);
}
}
export default App;
Do I need to add an async function or something, I'm fairly new to js so any help would greatly appreciated. I just don't know how to change the ipfs.add to make my code work.
I have also followed the same tutorial and ran into the same problem. The ipfs.add function does not accept a call function anymore. More information on that here: https://blog.ipfs.io/2020-02-01-async-await-refactor/
The solution is turn your saveTestBlobOnIpfs function into an async/await function. Like this:
saveTestBlobOnIpfs = async (event) => {
event.preventDefault();
console.log('The file will be Submitted!');
let data = this.state.buffer;
console.log('Submit this: ', data);
if (data){
try{
const postResponse = await ipfs.add(data)
console.log("postResponse", postResponse);
} catch(e){
console.log("Error: ", e)
}
} else{
alert("No files submitted. Please try again.");
console.log('ERROR: No data to submit');
}
}

How could I pass JSON object array result to my api URL? (In REACT)

I have to fetch 2 api from backend, and try to get the result from this two. but, at the moment, the JSON result I get from the first API is object Array in JSON. I need to pass the id from first API(using setState) to second API for path variables. But when I do in my way, it fail to retrieve the data. Consider the code below:
componentDidMount(){
// console.log(loginEmail)
fetch(`http://localhost:9000/api/item/list`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({data: res.data});
}
)
})
const id = this.state.data.id;
fetch(`http://localhost:9000/api/item/photo/view/${id}`,)
.then((resp)=>{
resp.json().then((res)=>{
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
this.setState({res});}
)
})
}
The problem is that fetch returns a Promise so, at the line
const id = this.state.data.id;
You do not have data populated yet.
You have to concatenate the two requests in a way like the following:
componentDidMount() {
fetch(`http://localhost:9000/api/item/list`)
.then((resp) => {
// return the id
})
.then((id) => {
fetch(`http://localhost:9000/api/item/photo/view/${id}`)
.then((resp) => {
// do what you need with the result
})
})
}
Fetch is asynchronous, which means javascript will
fetch data on the first call with no waiting, and continue
to the second fetch call where the id is not defined or Null.
In order to fix that you can use promises as follow
My code example
import React from "react";
class Home extends React.Component {
constructor() {
super();
this.state = {
res: [],
}
}
// http://jsonplaceholder.typicode.com/users
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res);
}
)
})
})
}
async componentDidMount() {
let data = await this.fetchData("http://jsonplaceholder.typicode.com/users");
console.log("data :", data);
let id = data[0].id;
console.log("Id :", id);
let newData = await this.fetchData(`http://jsonplaceholder.typicode.com/users/${id}`);
this.setState({ res: newData });
}
render() {
return (
<div>
Call API
</div>
)
}
}
export default Home
Adapted on your code
fetchData(url) {
return new Promise((resolve, reject) => {
fetch(url)
.then((resp) => {
resp.json().then((res) => {
console.log(res.data);
// localStorage.setItem('id', res.data.user_info.id);
resolve(res.data);
}
)
})
})
}
async componentDidMount() {
// console.log(loginEmail)
let data = await this.fetchData("http://localhost:9000/api/item/list");
let id = data.id;
let newData = await this.fetchData(`http://localhost:9000/api/item/photo/view/${id}`);
this.setState({ res: newData });
}
You need to make sure that each id gets its relevant results.
async componentDidMount() {
await fetch(`http://localhost:9000/api/item/list`)
.then(async (resp) => {
let req_ = resp.map((item)=>{
return await fetch(`http://localhost:9000/api/item/photo/view/${item.id}`)
})
let result = Promise.all(req_)
console.log(result)
})
}

TextDecoder failing in ES6 Promise recursion

I'm attempting to query an API which responds with a ReadableStream of XML.
The code below uses a recursive Promise. Recursive because it sometimes doesn't decode the stream in a singular iteration and this is whats causing my headache.
While I'm successfully fetching the data, for some reason the decoding stage doesn't complete sometimes, which leads me to believe it's when the stream is too large for a single iteration.
componentDidMount() {
fetch("http://thecatapi.com/api/images/get?format=xml&size=med&results_per_page=9")
.then((response) => {
console.log('fetch complete');
this.untangleCats(response);
})
.catch(error => {
this.state.somethingWrong = true;
console.error(error);
});
}
untangleCats({body}) {
let reader = body.getReader(),
string = "",
read;
reader.read().then(read = (result) => {
if(result.done) {
console.log('untangling complete'); // Sometimes not reaching here
this.herdingCats(string);
return;
}
string += new TextDecoder("utf-8").decode(result.value);
}).then(reader.read().then(read));
}
I think that the next iteration was sometimes being called before the current iteration had completed, leading to incorrectly concatenation of the decoded XML.
I converted the function from sync to async and as a regular recursive method of the component rather than a recursive promise with a method.
constructor({mode}) {
super();
this.state = {
mode,
string: "",
cats: [],
somethingWrong: false
};
}
componentDidMount() {
fetch("http://thecatapi.com/api/images/get?format=xml&size=med&results_per_page=9")
.then( response => this.untangleCats( response.body.getReader() ) )
.catch(error => {
this.setState({somethingWrong: true});
console.error(error);
});
}
async untangleCats(reader) {
const {value, done} = await reader.read();
if (done) {
this.herdingCats();
return;
}
this.setState({
string: this.state.string += new TextDecoder("utf-8").decode(value)
});
return this.untangleCats(reader);
}