SyntaxError: Unexpected token S in JSON at position 0 - javascript

I have a netlify function which returns a correct data as well as success message which I call to my api. Though when I tried to show the data in my react front end it gives me error with promise status rejected.
Promise{pending}
[[promiseStatus]]: rejected
[[PromiseValue]]: SyntaxError: Unexpected token S in JSON at position 0
function which reads data from graphql
readWeight.js
import fetch from 'node-fetch'
exports.handler = async() => {
console.log("inside");
const response = await fetch(
'https://graphql.fauna.com/graphql',
{
method: 'POST',
headers: {
Authorization: `Bearer ${API_SECRET}`
},
body: JSON.stringify({
query:`
{allweight{data{weight}}}
`
})
})
.then(res => res.json())
.catch(err => console.log(err))
//console.log(response.data.allweight.data.map(w=>console.log(w.weight)))
//console.log(response)
return {
statusCode: 200,
body: JSON.stringify(response)
}
}
api.js
const readAll = () => {
return fetch('/.netlify/functions/readWeight').then((response) => {
console.log(response)
return response.json()
})
}
api.js response
Response {type: "basic", url: "http://localhost:3000/.netlify/functions/readWeight", redirected: false, status: 200, ok: true, …}
type: "basic"
url: "http://localhost:3000/.netlify/functions/readWeight"
redirected: false
status: 200
ok: true
statusText: "OK"
headers: Headers {}
body: (...)
bodyUsed: true
__proto__: Response
app.js
import React, { Component } from 'react'
import api from './api'
export default class App extends Component {
state = {
weight: []
}
componentDidMount() {
// Fetch all todos
console.log(api.readAll())
api.readAll().then((t) => {
this.setState({
weight: weight
})
})
}
render(){
return(
<h1>Test
{this.state.todos}</h1>
)
}
}

Related

How to passing data from middleware to components/api in Next Js 13?

i just trying Next Js 13 middleware feature. But i confuse how to passing data from middleware to components/page/api.
For example i try to pass payload or who user is currently loggin.
Normally without middleware feature, i just make middleware file and if jwt verify true, i will send/pass payload data to my components/api
import {example} from 'middleware/example'
const payload = await example(req, res)
But if i using Next Js 13 feature and i read the docs, i just find how to send response like
return new NextResponse(
JSON.stringify({
success: false,
message: 'authentication failed'
}),
{ status: 401, headers: { 'content-type': 'application/json' } }
)
if i use that, it will return json data, and not continue the middleware chain, if i use
return NextResponse.next()
it will continue the middleware chain, but how do i passing my payload data to components/page/api?.
im trying like this
return NextResponse.next({tes: "tes"})
but i can't find how to get that data from components/api.
This is my middleware code
if (request.nextUrl.pathname.startsWith('/api/posts')) {
const requestHeaders = new Headers(request.headers)
const authorization = requestHeaders.get('authorization')
if (!authorization) {
return new NextResponse(
JSON.stringify({
success: false,
message: 'authentication failed'
}),
{ status: 401, headers: { 'content-type': 'application/json' } }
)
}
const authSplit = authorization.split(' ')
const [authType, authToken] = [
authSplit[0],
authSplit[1]
]
if (authType !== 'Bearer') {
return new NextResponse(
JSON.stringify({
success: false,
message: 'authentication failed'
}),
{ status: 401, headers: { 'content-type': 'application/json' } }
)
}
const payload = await verify(authToken)
if (!payload) {
return new NextResponse(
JSON.stringify({
success: false,
message: 'authentication failed'
}),
{ status: 401, headers: { 'content-type': 'application/json' } }
)
}
return NextResponse.next()
}

POST http://localhost:5000/task/mat 400 (BAD REQUEST)

I have this error in the console:
react_devtools_backend.js:4012 A non-serializable value was detected in an action, in the path: `meta.arg.config.adapter`. Value: ƒ xhrAdapter(config) {
return new Promise(function dispatchXhrRequest(resolve, reject) {
var requestData = config.data;
var requestHeaders = config.headers;
var responseType = config.resp…
Take a look at the logic that dispatched this action:
{type: '[GET] dataGrid/runTask/rejected', payload: undefined, meta: {…}, error: {…}}
error
:
{name: 'Error', message: 'Request failed with status code 400', stack: 'Error: Request failed with status code 400\n at …tp://localhost:3000/static/js/bundle.js:208909:7)'}
meta
:
{arg: {…}, requestId: 'XNHo_e78g2enuXNwLe_pQ', rejectedWithValue: false, requestStatus: 'rejected', aborted: false, …}
payload
:
undefined
type
:
"[GET] dataGrid/runTask/rejected"
[[Prototype]]
:
Object
can anyone tell me where is the problem because the backend works well.
and the part of code that is mentioned is:
const requestConfig = {
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
};
export const getReportsList = createAsyncThunk(
'\[GET\], dataGrid/reportsList',
async (\_) = \ > {
const response = await getData(ENDPOINTS.all_reports)
return response.data
}
)
I found out that the problem is related to the headers.
I call 2 times the headers so in headers I had the another one!
simply after that the error solved.
You could Modify Your Code like this.
const requestConfig = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}
export const getReportsList = createAsyncThunk(
'[GET], dataGrid/reportsList',
async (_, {getData, ENDPOINTS}) => {
const response = await getData(ENDPOINTS.all_reports, requestConfig)
return response.data
}
)
Note : The getData function and ENDPOINTS object need to be imported and provided to the createAsyncThunk middleware as dependencies in order to use them within the thunk.

How can I make an API call that depends on a value which is set by another call?

I have a login function where I am setting a token, that token is saved in a redux store, then, right after the login occurs, I need to make another call to the api which will feed the home screen with data. But in order to make that call, I need the token.
This is the homescreen component where I need to make that call:
// imports
import styles from '../../styles/HomeScreenStyles';
import { passengersDataAction } from './actions/homeScreen';
class HomeScreen extends Component {
static navigationOptions = {
header: null,
};
componentDidMount() {
this.GetPassengersData();
}
GetPassengersData = async () => {
// userToken is coming from the store
const { passengersDataActionHandler, userToken } = this.props;
if (userToken && userToken !== null) {
try {
const response = await fetch(
'http://myAPI/public/api/getPassengers',
{
method: 'POST',
headers: {
Authorization: `Bearer ${userToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
);
const responseJson = await response.json();
passengersDataActionHandler(responseJson.success.data);
} // catch ...
}
};
render() {
return <TabView style={styles.container} />;
}
}
// export
By the time GetPassengersData is called userToken is not present yet, so my request goes directly to the catch error callback.
How can I handle it?
EDIT:
The API call I put above is the one where I need the token.
Call to get the logindata:
import { Alert, AsyncStorage } from 'react-native';
import { has } from 'lodash';
import PropTypes from 'prop-types';
const FetchLoginData = async (
username,
password,
navigation,
userTokenActionHandler,
) => {
try {
const response = await fetch(
'http://myAPI/public/api/driverlogin',
{
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: username, password }),
},
);
const responseJson = await response.json();
if (has(responseJson, 'error')) {
Alert.alert('Error', 'Please check your credentials.');
} else {
// HERE I SET THE TOKEN
await AsyncStorage.setItem('userToken', responseJson.success.token);
userTokenActionHandler(responseJson.success.token);
navigation.navigate('App');
}
} catch (error) {
Alert.alert(
'Error',
'There was an error with your request, please try again later.',
);
}
};
FetchLoginData.propTypes = {
navigation: PropTypes.shape({}).isRequired,
userTokenActionHandler: PropTypes.func.isRequired,
};
export default FetchLoginData;
You can put your second call here :
try {
const response = await fetch(
'http://myAPI/public/api/getPassengers',
{
method: 'POST',
headers: {
Authorization: `Bearer ${userToken}`,
Accept: 'application/json',
'Content-Type': 'application/json',
},
},
);
const responseJson = await response.json();
passengersDataActionHandler(responseJson.success.data);
// **put second call here you have token here send it to second api call**
}

Axios post stay on pending

This is a simple Post request using Axios inside Vue:
import axios from 'axios'
export default {
name: 'HelloWorld',
props: {
msg: String
},
mounted () {
const code = 'test'
const url = 'http://localhost:3456/'
axios.post(url, code, { headers: {'Content-type': 'application/x-www-form-urlencoded', } }).then(this.successHandler).catch(this.errorHandler)
},
methods: {
successHandler (res) {
console.log(res.data)
},
errorHandler (error) {
console.log(error)
}
}
}
The Get method works fine. But Post stay as "Pending" on Network tab. I can confirm that there is a Post method on my webservice and it return something (tested on Postman).
UPDATE
Sending code as a param:
axios(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
params: {
code : 'test'
},
}).then(this.successHandler).catch(this.errorHandler)
WEBSERVICE
server.post('/', (req, res, next) => {
const { code } = req.params
const options = {
validate: 'soft',
cheerio: {},
juice: {},
beautify: {},
elements: []
}
heml(code, options).then(
({ html, metadata, errors }) => {
res.send({metadata, html, errors})
next()
})
})
I think there's issue with your axios request structure.
Try this:
const URL = *YOUR_URL*;
axios(URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
data: *YOUR_PAYLOAD*,
})
.then(response => response.data)
.catch(error => {
throw error;
});
If you're sending a query param:
axios(URL, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
params: {
code: 'your_string'
},
})
if it is path variable you can set your url:
const url = `http://localhost:3456/${code}`
Let me know if the issue still persists
I also was facing the same. Network call was pending all the time and Mitigated it by passing the response back from server.js(route file) e.g(res.json(1);) and it resolved the issue

Fetch not receiving error message from Node Js

What's happening:
My project has a route called /login, when an user to try do login and he is not "MANAGER" (attribute of the database), it should give a 401 error. In the back-end it is working but the error is not received in the fetch of the front-end, I don't know why.
My code Node.js:
const {
findByMail
} = require('../data/acl/acl.model');
module.exports =
async function isAuthenticated(req, res, next) {
const acl = await findByMail(req.body.username);
if (acl && acl.role !== "MANAGER") {
res.status(401).send("You dont have access")
}
next()
}
My front-end:
handleLogin = async() => {
try {
this.setState({
loading: true
});
const rawResponse = await fetch('/login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ...this.state
}),
});
const response = await rawResponse.json();
localStorage.setItem('user-token', response.token);
this.setState({
loading: false
});
} catch (err) {
this.setState({
loading: false
});
console.log(err);
}
};
Console.log:
SyntaxError: Unexpected token F in JSON at position 0
at Login._callee$ (login.js:18)
at tryCatch (runtime.js:62)
at Generator.invoke [as _invoke] (runtime.js:296)
at Generator.prototype.(anonymous function) [as next] (https://localhost:3000/static/js/bundle.js:103406:21)
at step (background.login.png:1)
at background.login.png:1
login.js:18 POST https://localhost:3000/login 401 ()
I don't know what's wrong, could somebody help me?
The problem is simple, fetch() doesn't recognize a 401 code as an unacceptable response so your catch will not be called, instead it will continue the code like a 200 code.
After you got the response you should do this :
handleLogin = async() => {
try {
this.setState({
loading: true
});
const rawResponse = await fetch('/login', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({ ...this.state
}),
});
if(!rawResponse.ok){
this.setState({
loading: false
});
}
else{
const response = await rawResponse.json();
localStorage.setItem('user-token', response.token);
this.setState({
loading: false
});
}
} catch (err) {
this.setState({
loading: false
});
console.log(err);
}
};

Categories