I'm creating a user register and I'm using the redux toolkit. When the user details are not in the local storage I'm setting it to null. But since the beginning the user is undefined, it should assign it a null value but I'm getting this error:
Uncaught SyntaxError: Unexpected token u in JSON at position 0
due to this code:
// Get user from localStorage
const user = JSON.parse(localStorage.getItem("user"));
//initials state
const initialState = {
user: user ? user : null,
isError: false,
isSuccess: false,
isLoading: false,
message: "",
};
How should I write it or what I'm doing wrong? I understand the value undefined is what is being stringified.
Any time you see Unexpected token u in JSON at position 0, it's almost certainly because you're trying to pass undefined to JSON.parse. JS will automatically convert it to the string "undefined", which is not valid JSON.
Something like JSON.parse(localStorage.getItem("user") || "null") should do the trick. This will pass the string "null" (which is valid JSON) instead if localStorage.getItem("user") returns anything "falsy".
This also means you don't need the user ? user : null later on - you can replace that with just user.
Clearing local storage solved the issue.Thank you
Related
I'm using Angular 11, and have to post some data to a backend service. Here's the data I need to post:
interface User {
id: Guid; // Guid is just a type alias to string, with some validation checks
email: string;
role: Role
}
enum Role {
User = 0,
Administrator = 1
}
Now the problem comes when I try to post to my backend using the default HttpClient from Angular. Here's the code:
createOrUpdateUser(user: User): Observable<User> {
return this.http.post<User>(`${this.baseUrl}/${this.userUrl}/${this.userCreateOrUpdate}`, user);
}
This works fine, but the JSON sent is "wrong". It sends this:
{
"id": "2abe50d6-4c81-4ace-ad95-c8182d4384a3",
"email": "someEmail#example.org",
"role": "0"
}
Where as the backend is expecting this
{
"id": "2abe50d6-4c81-4ace-ad95-c8182d4384a3",
"email": "someEmail#example.org",
"role": 0
}
The difference being the backend expects "role": 0, but Angular sends "role": "0". How can I make Angular send "role": 0?
This is may not be a good idea. But it will be helped you.
createOrUpdateUser(user: User): Observable<User> {
user.role = Number(user.role);
return this.http.post<User>(`${this.baseUrl}/${this.userUrl}/${this.userCreateOrUpdate}`, user);
}
you can use + to make it as number before sending it api user.role = +user.role. Some where else you are assigning value of role in user object which is making it as a string. its not enum issue.
TypeScript is compiled to plain old javascript code, where type enforcement is more or less non-existent. This means that, in theory, you might be assigning a string to your User model.
There can be multiple reason - i.e. you receive it this way from backend, assign it to a variable and re-send later without modifying the value. Or, for example, the User comes from a FormGroup which passes the value as a string. You can even have TypeScript code omit type checks:
let user: User = {
id: '2abe50d6-4c81-4ace-ad95-c8182d4384a3',
email: 'someEmail#example.org',
role: Role.Administrator
}
user['role'] = "2" // Not a valid enumeration
So, to instead of going for some strange workaround like using +user.role in the mapping, perhaps look for where / how the value is assigned in the first place.
As it is not really clear if it gets sent from angular or received from server as string we can debug a bit to find the right place to investigate (angular frontend or backend)
You can investigate by logging console.log(typeof user.role)and see what it returns. Also have a look at what gets sent from frontend to backend using Chrome Devtools -> Network -> click on the request -> and scroll down on first tab to see what data gets sent.
What might happen is frontend to send the right data type (integer) for the role and backend interpret it as string.
In this case you could just use parseInt(user.role) in the backend as a fallback or investigate how to get the integer type on the backend body request instead of string.
I have created a Home.js and included inside App.js of my react app.I want to fetch json data but I am getting the following error-
My Code- https://stackblitz.com/edit/react-kwaooy?file=src/App.js
For initial load your this.state.lists.regionData will be undefined and you are accessing the undefined value that might be the issue for crashing the application.
Change your state value like below,
this.state = {
lists: {
regionData: [],
activeCases: '',
activeCasesNew: '',
deaths: ''
}
};
You need to check what you are actually storing in the list state from the response. What I see is that you are storing response.data but you might actually want to store regionData from the response. This will allow map to iterate over the regionData values and not show this error.
I'm using knex with MYSQL. I have a function that I called to show the data to the user, Also I'm using a view table which has 5 right join on it and I think it will take some time to return values from the table plus I added the WHERE condition on my knex and it looks like this :
var showClass = (teacherId , ClassId){
return new Promise((resolve , reject)=>{
knex.select().from('v_cardex_details').where({teacherId }).andWhere({id : ClassId}).then(classes =>{
resolve(classes)
}).catch(err=>{
console.error(`Show Teacher class Error: ${err}`)
reject (err)
})
})
}
and I call this general function to response some request something like this
exports.EditClass = (req,res)=>{
knex('Table').update({//Some update stuff here}).then(()=>{
showClass(req.user.id, req.params.id).then(data=>{
return res.status(200).json({data , message:''})
})
}).catch()
}
With the same input, this function after updating returns value and some times it returns an empty string, especially when it's on the hosting server most of the time it returns nothing but { message : '' }
Try to create simplified code by removing all the unnecessary wrappers and you might find where your problem is. AFAIK there is no way that that your {data , message:''} would create an object containing just {message: ''} without any additional attributes.
> var data = []
undefined
> {data, foo:1}
{ data: [], foo: 1 }
> data = undefined
undefined
> {data, foo:1}
{ data: undefined, foo: 1 }
> {data1, foo:1}
ReferenceError: data1 is not defined
The problem you are experiencing does not exist in from the code you have shared (though there are syntax errors and other problems).
EDIT:
res.json() uses JSON.stringify() to convert js object to JSON strings. So if value of data in your code is undefined instead of and array, that could explain the behavior you are experiencing:
λ node
> JSON.stringify({ test: undefined })
'{}'
As you can see JSON.stringify() omits the attributes with value undefined from the output JSON string.
I'm following an angular-nodeJS tutorial and I'm trying to recover data from a MySQL database. Here's my db creation script:
CREATE DATABASE ng_games_db;
USE ng_games_db;
CREATE TABLE games (
id INT (11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(180),
description TEXT(255),
image VARCHAR(200),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
My db connection works cause I can add entries to my only table from my app. However, when I try to get the data with this method:
public async list (req : Request, res : Response) : Promise<void> {
const games = await pool.query('SELECT * FROM games');
res.json(games);
}
I get the following error:
(node:5828) UnhandledPromiseRejectionWarning: TypeError: Converting circular structure to JSON
--> starting at object with constructor 'Query'
| property '_timer' -> object with constructor 'Timer'
--- property '_object' closes the circle
at JSON.stringify (<anonymous>)
at stringify (C:\Users\Dave\Documents\angular-mysql-crud\server\node_modules\express\lib\response.js:1123:12)
at ServerResponse.json (C:\Users\Dave\Documents\angular-mysql-crud\server\node_modules\express\lib\response.js:260:14)
at C:\Users\Dave\Documents\angular-mysql-crud\server\build\controllers\gamesController.js:23:17
at Generator.next (<anonymous>)
at fulfilled (C:\Users\Dave\Documents\angular-mysql-crud\server\build\controllers\gamesController.js:5:58)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
I've been searching the internet for a while trying to fix it but I've had no luck so far.
EDIT: Here is a library I've used before that might work for your situation:
https://www.npmjs.com/package/flatted
JSON.stringify doesn't handle circular references very well, like other serializers might pass a reference, stringify() crashes. You can try this, which will remove circular references:
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
JSON.stringify(games, getCircularReplacer());
// {"otherData":123}
Here is a link where the code snippet came from:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
In the footnotes of the link above, there is also mention of cycle.js which handles circular references.
https://github.com/douglascrockford/JSON-js/blob/master/cycle.js
Ultimately, you need to find a JSON serializer/ deserializer that is capable of decoding these references.
FOR PEOPLE STILL HAVING ISSUES:
For those who still have an issue with this after adding the flatted package, you need to add this line in after you create your database pool: pool.query = util.promisify(pool.query); - source: https://mhagemann.medium.com/create-a-mysql-database-middleware-with-node-js-8-and-async-await-6984a09d49f4
If you are using typescript it will complain but simply add // #ts-ignore above it and you should be fine.
You will now be able to make mysql select queries using try/catch and async/await!!
This command works fine for your problem:
pool.query ('SELECT * FROM games', function (err, rows) {res.send (rows);});
I have problems with afterSave implementing my signup logic.
What I have to do is to add a transaction in Wallet class when user makes the registration, giving him some credits. So i have my cloud code function:
// Add welcome bonus on signup
Parse.Cloud.afterSave(Parse.User, (request) => {
// commit transaction only on signup completed with phone number
if (request.object.get('username')) {
const wallet = new Parse.Object('Wallet')
wallet.set('value', 100)
wallet.set('action', '+')
wallet.set('description', 'welcome bonus')
wallet.set('user', {
__type: 'Pointer',
className: '_User',
objectId: request.object.id
})
wallet.save(null,{useMasterKey: true}).then(
(result) => console.log('objectId',result.id),
(error) => console.log('code:',error.code,'message:',error.message)
)
}
})
Since Parse.Cloud.useMasterKey() is deprecated I follwed the Parse doc on how to use the useMasterKey option on save method, but i still got this error:
info: afterSave triggered for _User for user undefined:
Input: {...} className=_User, triggerType=afterSave, user=undefined
code: 107 message: Received an error with invalid JSON from Parse: Cannot POST /classes/Wallet
And this is my Wallet table:
| value: Number | action: String | description: String | user: Pointer<_User> |
And the default columns createdAt, updatedAt, objectId and ACL
I'm working on localhost.
Any ideas on what's going on?
I would bet this is an issue with the way you're setting the User. If the field is set to be a pointer field to a user object, all you have to do is set wallet.set('user', request.object); The rest of the request looks fine, so my gut tells me it just isn't liking that JSON format for your set. I.e. when I set a pointer on the dashboard, I just type in the object ID. I don't format it like a pointer.
Also, this is gonna get triggered any time you save a user, so it isn't going to do what you want beyond this issue anyway.