how to read properly a json string in react native - json

I sent to asyncStorage all the info as stringify,
i tried to parse it.
this is what i get from console log:
"{\"metadata\":{\"lastSignInTime\":1610728860334,\"creationTime\":1610728860334},\"phoneNumber\":null,\"displayName\":null,\"isAnonymous\":false,\"providerData\":[{\"email\":\"ad#ad.com\",\"phoneNumber\":null,\"uid\":\"ad#ad.com\",\"photoURL\":null,\"displayName\":null,\"providerId\":\"password\"}],\"email\":\"ad#ad.com\",\"emailVerified\":false,\"providerId\":\"firebase\",\"photoURL\":null,\"uid\":\"3lkoKoMxQSMKeSxFOyysESt3oKh1\"}"
and i need to get email and uid seperate.
how do I get in that object? i tried user.email or user.providerData.email non of them work.
any suggestion?
edited:
here is the object I get from firebase
let res = await auth().createUserWithEmailAndPassword(Email, Password)
if (res) {
console.log( "?", res)
this.setState({ userData: JSON.stringify( res.user) });
this.storeToken(JSON.stringify(res.user));
then I store the token in async:
async storeToken(user) {
console.log('set user register: ', user)
try {
await AsyncStorage.setItem("userData", JSON.stringify(user));
} catch (error) {
console.log("Something went wrong", error);
}
}
and I get the object from above.
const readData = async () => {
console.log('data === ')
try {
const data = await AsyncStorage.getItem('userData')
let _data = JSON.parse(data);
console.log('data === ', data)

If you share code block it'll be easy for us.
Here is general answer.
Console log shows its still in string format. I use this separate file to read and write json to AsyncStorage. You can either use this OR match to see your mistake.
import AsyncStorage from '#react-native-community/async-storage';
const Api = {
storeData: async function (name, value) {
try {
await AsyncStorage.setItem(name, value);
return true;
} catch (error) {
return false;
}
},
readData: async function (name) {
let value = null;
try {
value = await AsyncStorage.getItem(name)
return JSON.parse(value);
} catch (e) {
return [];
}
},
}
export default Api;

after few console log I was able to get it by double parsing the object.
let _data = JSON.parse(JSON.parse(data));
console.log('data === ', _data.email)
and seem to work.

Related

Promise or Callback, which one is better to use with NodeJS?

I found that there are 2 different ways to write node functions using promise or callback, the first way is like following defining the findByEmail function:
class Users{
static async findByEmail(email: any ) : Promise<Users | undefined>{
const user: any = await Pools.execute(
"SELECT * FROM users WHERE email = ?",
[email])
.then(rows => {
return rows[0];
})
.catch(err => console.log(err) );
return user;
};
}
router.post(
"/api/users/signin",
async (req: Request, res: Response , next: NextFunction) => {
const { email, password } = req.body;
const existingUser = await Users.findByEmail(email);
});
And the second way would be like:
declare global {
namespace Express {
interface Response {
user?: Users;
}
}
}
static async findByEmail(req: Request, res: Response) {
const user = await Pools.execute(
"SELECT * FROM users WHERE email = ?",
[req.body.email])
.then(rows => {
res.user = rows[0];
})
.catch(err => console.log(err) );
};
router.post(
"/api/users/signin",
async (req: Request, res: Response , next: NextFunction) => {
await Users.findByEmail(req, res);
const existingUser = res.user;
});
I am not sure if this is a "opinion based" question or not? However my purpose of asking this is to know which way is a better practice and why? According to performance and other possible issues?
In particular I like to know either it is better to write functions with the return value or using response object to add the returning value to that inside the then() function, like .then(res.user = user) instead of const user = await pool.execute(SELECT ...) ?
Here's a way to impalement that makes the following improvements:
Makes findByEmail() into a utility function that is independent of the req and res objects and thus can be used generally.
Properly propagates all errors from findByEmail() back to the caller.
Implements some validation checks on incoming email field and makes separate error path for that.
Log all errors on the server
Check for all error conditions from the database request
Not mixing .then() and await.
Here's the code:
// resolves to null if email not found
// rejects if there's a database error
static async findByEmail(email) {
const rows = await Pools.execute("SELECT * FROM users WHERE email = ?", [email]);
if (!rows || !rows.length || !rows[0]) {
return null;
}
return rows[0];
};
router.post("/api/users/signin", async (req: Request, res: Response, next: NextFunction) => {
try {
// validate incoming parameters
if (!req.body.email) {
let errMsg = "No email value present in incoming signin request";
console.log(errMsg);
res.status(400).send(errMsg);
return;
}
let user = await Users.findByEmail(req.body.email);
if (!user) {
// do whatever you would do if user tries to signin with non-existent email
// presumably return something like a 404 status
} else {
// do whatever you wanted to do here with the user object after login
}
} catch(e) {
// some sort of server error here, probably a database error, not the client's fault
console.log(e);
res.sendStatus(500);
}
});

Cannot map results from API

I'm trying to dynamically generate routes in my next.js application. I have an api called getUsers that returns something like this:
{"users":[{"_id":"639a87ae8a128118cecae85b","username":"STCollier","image":"https://storage.googleapis.com/replit/images/1641322468533_db666b7453a6efdb886f0625aa9ea987.jpeg","admin":false,"likedPosts":["639e34c5991ecaea52ace9e4","639e34c7991ecaea52ace9e7","639e34c7991ecaea52ace9ea","639e39a216a642f686a28036","639e39a216a642f686a28037","639e3b3d8cdebd89d9691f97","639e3b3d8cdebd89d9691f98","639e3b3e8cdebd89d9691f9d","639e3b5a8cdebd89d9691fa0","639e3b5c8cdebd89d9691fa3","639e3b5c8cdebd89d9691fa6"],"dislikedPosts":[""]},{"_id":"639a88abc4274fba4e775cbe","username":"IcemasterEric","image":"https://storage.googleapis.com/replit/images/1646785533195_169db2a072ad275cfd18a9c2a9cd78a1.jpeg","admin":false,"likedPosts":[],"dislikedPosts":[]}
So I know the API works succesfully, but when trying to get these api results and generate a page for each username, I get an error stating:
TypeError: users.map is not a function
Here's my code for generating the routes:
//pages/user/[username].js
const Get = async (url) => {
return await fetch(url).then(r => r.json());
}
export async function getStaticPaths() {
const users = Get('/api/getUsers')
return {
paths: users.map(u => {
const username = u.users.username
return {
params: {
username
}
}
}),
fallback: false
}
}
What is wrong with my getStaticPaths() code? I know that the API is working, so why can't I map the results?
And if anyone needs the code for api/getUsers, here is that:
import clientPromise from "../../lib/mongodb";
import nc from "next-connect";
const app = nc()
app.get(async function getUsers(req, res) {
const client = await clientPromise;
const db = client.db("the-quotes-place");
let users = []
try {
const dbUsers = await db
.collection("users")
.find({})
.toArray();
users = dbUsers
return res.json({
users: JSON.parse(JSON.stringify(users)),
success: true
})
} catch(e) {
return res.json({
message: new Error(e).message,
success: false,
});
}
})
export default app
Thanks for any help!!
Modify Get method to return an async value instead of Promise.
As Get is an async method, you need the await in getStaticPaths method.
const Get = async (url) => {
let response = await fetch(url);
return await response.json();
}
export async function getStaticPaths() {
const users = await Get('/api/getUsers');
...
}

Unable to fetch data from server due to serialization problem using NextJS?

I'm currently using axios and NextJS.
I currently have this code in my component:
export async function getServerSideProps(context) {
const data = await getVideo(context.query.id);
console.log('data: ', data);
// console.log('context: ', context);
console.log('context params: ', context.params);
console.log('context query: ', context.query);
if (!data) {
return { notFound: true };
}
return {
props: {
videoId: context.params.id,
videoSlug: context.params.slug,
videoContent: data
}
};
}
This getserverSideProps call the function of getVideo which looks exactly like this:
export const getVideo = (id) => async (dispatch) => {
dispatch({ type: CLEAR_VIDEO });
try {
console.log('Action file: ', id);
const res = await api.get(`/videos/${id}`);
return dispatch({
type: GET_VIDEO,
payload: res.data
});
} catch (err) {
dispatch({
type: VIDEO_ERROR,
payload: { msg: err.response?.statusText, status: err.response?.status }
});
}
};
Said function goes through my api function to make requests to backend:
import axios from 'axios';
import { LOGOUT } from '../actions/types';
import { API_URL } from '../config';
const api = axios.create({
baseURL: `${API_URL}/api/v1`,
headers: {
'Content-Type': `application/json`
}
});
/**
intercept any error responses from the api
and check if the token is no longer valid.
ie. Token has expired
logout the user if the token has expired
**/
api.interceptors.response.use(
(res) => {
res;
console.log('Res: ', res.data);
},
(err) => {
if (err?.response?.status === 401) {
typeof window !== 'undefined' &&
window.__NEXT_REDUX_WRAPPER_STORE__.dispatch({ type: LOGOUT });
}
return Promise.reject(err);
}
);
export default api;
It works great when doing POST, PUT,PATCH requests.
As you can see, I'm doing a console.log('data: ',data) but it returns [AsyncFunction (anonymous)] whenever I read the terminal; on the other hand, the front-end returns this error:
Server Error Error: Error serializing .videoContent returned from
getServerSideProps in "/videos/[id]/[slug]". Reason: function
cannot be serialized as JSON. Please only return JSON serializable
data types.
Does anyone knows how to solve this?
NOTE: I'm using react-redux, redux and next-redux-wrapper.
That is because your getVideo function returns another function. The right way to call it would be:
const data = await getVideo(context.query.id)()//<- pass in the dispatch here
But you should not use redux in the backend like that. I think you can completely remove it.
export const getVideo async (id) => {
try {
console.log('Action file: ', id);
const res = await api.get(`/videos/${id}`);
return res.data
});
} catch (err) {
return { msg: err.response?.statusText, status: err.response?.status }
}
};
// call
const data = await getVideo(context.query.id)

Node.JS: How to scrape a json page for specific data

I would like to scrape this page: calendar events
for specific data, like formattedDate and description. How do I go about that in a module in Node.JS. I am having a hard time understanding the process in Node.JS.
Any help would go a long way, thanks in advance.
it's pretty simple, you can import the request module and use it. For example, see code below.
const request = require("request");
request("MY_URL", (error, response, body) => {
console.log('body:', body);
});
Also, you can try this here, on Repl.it
First of all, you need to parse your JSON, this allows you to access fields from received json.
const data = JSON.parse(body);
Now, if you want to access some information about an event you need to loop events and access what you need, something like:
const events = data.bwEventList.events;
events.map((data, index) => console.log(data.calendar))
Final code also on Repl.it
from nodeJS docs here
const http = require('http');
http.get('http://umd.bwcs-hosting.com/feeder/main/eventsFeed.do?f=y&sort=dtstart.utc:asc&fexpr=(categories.href!=%22/public/.bedework/categories/sys/Ongoing%22%20and%20categories.href!=%22/public/.bedework/categories/Campus%20Bulletin%20Board%22)%20and%20(entity_type=%22event%22%7Centity_type=%22todo%22)&skinName=list-json&count=30', (res) => {
const { statusCode } = res;
const contentType = res.headers['content-type'];
let error;
if (statusCode !== 200) {
error = new Error('Request Failed.\n' +
`Status Code: ${statusCode}`);
}
if (error) {
console.error(error.message);
// consume response data to free up memory
res.resume();
return;
}
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => { rawData += chunk; });
res.on('end', () => {
try {
const parsedData = JSON.parse(rawData);
console.log(parsedData["bwEventList"]["resultSize"]);
} catch (e) {
console.error(e.message);
}
});
}).on('error', (e) => {
console.error(`Got error: ${e.message}`);
});
see console.log(parsedData["bwEventList"]["resultSize"]);
slice parsedData as an array until you get what you want

How to handle Promise in nodejs

I'm trying to execute a callback function in nodejs, using expressjs and angular 2 (i don't know if the angular2 part it's relevant).
What I do is:
I have a formular in angular2, with that I send a get request to my API route, then I send the text field in the formular to the URL via get, then I do an MYSQL query to look into a phonebook database, and I'm expecting to get a complete user with his details, from the phonebook.
Formular:
<div class="container">
<div class="col-md-4">
<h1>Addressbook</h1>
<form [formGroup]="searchForm" (ngSubmit)="doSearch($event)">
<input formControlName="searchString" type="text" placeholder="Name">
<button type="submit">Search</button>
</form>
</div>
</div>
First function, doSearch:
doSearch(event) {
let formData = this.searchForm.value;
var searchString = this.searchForm.value.searchString;
this.http.get('/phonebook/search/'+searchString, function(req, res){}).subscribe(
function(response) {
console.log("Success Response");
},
function(error) { console.log("Error happened" + error)},
function() { console.log("the subscription is completed")}
);
}
This calls to the route sending a parameter, so not so hard.
Now the create router gets into the game:
public static create(router: Router, basePath: string) {
console.log("[SearchRoute::create] Creating routes for /search.");
// call the function for retrieving the address book results
router.get(basePath + "/search/:searchString", (req: Request, res: Response, next: NextFunction) => {
console.log("## [SearchRoute] Called GET /search.");
var object = searchUser(req);
console.log(object);
});
}
And finally, the function searchUser gets called:
function searchUser(req: Request) {
console.log("searchUser Function executed.");
var searchString = req.params.searchString;
var query = p_query('SELECT XXXX')
.then(function (results) {
console.log("query executed and all okay");
return (results);
})
.catch(function (error) {
console.error("Wooopsi", error);
});
console.log("query result: "+query);
}
Additionally, I post here the new query function that I build to be able to handle promises (which I don't know if it was the best choice):
function p_query(q) {
return new Promise(function (resolve, reject) {
// The Promise constructor should catch any errors thrown on
// this tick. Alternately, try/catch and reject(err) on catch.
myMYSQL.db.query(
q,
function (error, results) {
if (error)
reject(error);
resolve(results);
});
})
};
So, what I actually want to do, what's my issue?
I want to send the result of the query back to the client (the angular2 formular), and I was not being able to do it...
So after this really long post, I really appreciate if you read til here, and sorry for the complicated question!
PS: I know i explain myself really bad :(
Regards,
Daniel
In this official angular 2 documentation on the http client they propose to put the http logic into a separate service. I've setup it similar to the example just for a search.service.ts:
import { Injectable } from '#angular/core';
import { Http, Response,Headers, RequestOptions,URLSearchParams }
from '#angular/http';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';
#Injectable()
export class SearchService {
constructor(private http: Http) {
}
getSearchResult(searchString) : Observable<any> {
return this.http.get('/phonebook/search/'+searchString)
.map(this.extractData)
.catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body;
}
private handleError (error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
return Observable.throw(errMsg);
}
}
In your component import the service and do the code snippets:
// don't forget to put the service in the app.modul or the component providers!
constructur(public mySearchService : SearchService) {}
// in your doSearch of your component:
doSearch(event) {
let formData = this.searchForm.value;
var searchString = this.searchForm.value.searchString;
mySearchService.getSearchResult(searchString).subscribe(
data => mylist.data, // or which datastructure I want to write to.
error => console.error(error) // or how I log the errors..
);
}
EDIT: The search_user in your database model:
function searchUser(searchString) {
console.log("searchUser Function executed.");
return myMYSQL.db.select('phonebookentry', {
pbe_lastname: searchString, pbe_syncstate: 'new'
}) // returning the promise/observable to the main function...
} // Currently I don't know, how the returned data looks like.
On the node/express side in the router send it with res.json EDIT: use asynchronous call to searchUser:
router.get(basePath + "/search/:searchString",
(req: Request, res: Response, next: NextFunction) => {
console.log("## [SearchRoute] Called GET /search.");
searchUser(req)
.then( data => res.json(data);console.log(data) )
.catch (error => console.log(error));
});
You should go with recursive callback with each query results try to enjoy the beauty of async platform.
Send data to client via
res.send(data);
Your answer it's completely perfect, i understand everything! The only problem that i'm facing now, its this one:
I'm calling the function searchUser, and it doesn't return anything, just an undefined object, so i quess i'm not doing the return correctly.
That's my searchUser function:
function searchUser(searchString) {
console.log("searchUser Function executed.");
myMYSQL.db.select('phonebookentry', {
pbe_lastname: searchString,
pbe_syncstate: 'new'
}).then(function (user) {
console.log("user before: "+user);
return (user);
}).catch(function (err) {
console.log(err);
})}
Thank you so much for your useful answer! I'm almost finished here