I have created signalR connection in my ReactJS application, whenever i load page for the first time then i get an error "Error: Failed to complete negotiation with the server: Error: Unauthorized" but when i reload the page again then it works fine i.e. it get connected properly.
I just want to connect the signalR connection properly when page load for the first time without the need to reload it again
Here is my code for signalR connection:
export default class Dashboard extends Component {
constructor(props) {
super(props)
this.state = {
signalRURL: 'https://****/?hub=broadcast',
accessToken: '',
alertData: {}
}
}
getURL = () => {
return new Promise((resolve, reject) => {
return axios({
url: 'https://*****/api/SignalRConnection',
method: "get",
headers: {
"content-type": "application/json",
"Access-Control-Allow-Origin": "*"
},
})
//Get the SignalR connection information which contains Url and Access token,
//by calling the SignalRConnection API.
.then(response => {
localStorage.setItem("access_key", response.data.accessToken)
console.log("response", response)
resolve(response);
})
.catch(error => {
reject(error);
});
});
}
componentDidMount = () => {
this.getURL().then(data => {
console.log("dataaa", data)
})
.catch(err => {
console.log("error", err)
})
//Create the Hub connection using SignalR.HubConnectionBuilder.
const options = {
accessTokenFactory: () => localStorage.getItem("access_key")
};
const hubConnection = new SignalR.HubConnectionBuilder()
.withUrl(this.state.signalRURL, options)
.configureLogging(SignalR.LogLevel.Information)
.build();
hubConnection.on('notify', data => {
this.setState({alertData: data})
console.log("state data",this.state.alertData)
console.log(data);
});
hubConnection
.start()
.catch(
error => console.error(error)
);
hubConnection.serverTimeoutInMilliseconds = 6000000;
hubConnection.keepAliveIntervalInMilliseconds = 3000000;
hubConnection.onclose((error) => {hubConnection.start();
console.error(`Something went wrong: ${error}`); });
}
render() {
return (
<div>
</div>
)
}
}
This is the error message i get everytime when i load the page for the first time
Related
I am trying to get the error status code that would be 413 in Axios catch block. I have tried different solutions nothing worked for me. Could you please review what is going wrong.
uploadNewDatDocuments(datId, files = [], additionalInfo = {}) {
return new Promise((resolve, reject) => {
let url = new URL(this.baseUrl + this.uploadDocument.replace('{id}', datId));
Object.keys(additionalInfo).forEach(queryParam => url.searchParams.set(queryParam, additionalInfo[queryParam]));
let formData = new FormData();
files.forEach(file => formData.append('files', file));
axios
.post(url.toString(), formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
.then(response => {
resolve(response.data);
})
.catch(error => {
console.log("error occurred")
reject(error);
}).finally(error=>{
console.log(error);
})
});
}
Here is my Action code.
export function uploadNewDocuments(datId, additionalInfo = {}, attachments = [], comment = {}) {
return dispatch => {
datService
.uploadNewDatDocuments(datId, attachments, additionalInfo)
.then(response => {
const attachmentsIds = response.map(attachment => attachment.id);
dispatch(
DatCommentActions.addDatNewComment(datId, {
...comment,
message: { ...comment.message, attachments: attachmentsIds }
})
);
})
.catch(error => {
dispatch(MessageActions.showMessage({ message: error.response.data.message }));
console.error(error);
});
};
}
413 Request Entity Too Large is not actually error, its a not successful response and catch wont fire unless there is actual error on response.
What you could do is check response.status and based on that and write own error handling.
I am getting a token to access an API endpoint and I want to send this token to my server-side app (expressJS) to retreive the data.
I have the following for my react app:
export default class Account extends React.Component {
constructor() {
super();
this.state = {
token: null,
response: {
}
};
this.getCurrentlyPlaying = this.getCurrentlyPlaying.bind(this);
}
componentDidMount() {
// Set token
let _token = hash.access_token;
if (_token) {
this.setState({
token: _token
});
const cookies = new Cookies();
cookies.set('token', _token, { path: '/' });
console.log(cookies.get('token'));
this.getCurrentlyPlaying(_token);
}
}
getCurrentlyPlaying() {
fetch(`http://localhost:3001/account`)
.then(res => res.json())
.then(data => {
this.setState ({
response: data
})
console.log(data);
});
}
render() {
if (this.state.response[0].is_playing === true) {
return (
<p> Something is playing</p>
);
}
else {
return (
<p> Nothing is playing</p>
);
}
}
}
In my express app, I have the cookie being gotten but I'm not sure if it actually is getting the cookie created by the react app:
router.get('/account', (req, res) => {
const config = {
headers: {
'Authorization': `Bearer ${req.session.token}`
}
};
fetch(`${CONFIG.spotifyUrl}/me/player/currently-playing `, config)
.then(html => html.json())
.then(json => {
res.json(json);
});
});
module.exports = router;
Can someone tell me where I'm going wrong please?
To parse cookies in backend with express, a good choice is to use the https://github.com/expressjs/cookie-parser middleware.
Provided you are using setup something similar to below
const cookieParser = require('cookie-parser');
app.use(cookieParser());
Every Request object on server will have cookies information in the req.cookies property. So in your case it should be req.cookies.token
I am trying to build a generic function for my endpoints, using Axios and React. Generic because I have always the same header and I do not want to repeat a lot of code for each of my components.
To do that, I built this function (sorry, a lot of comments that I will remove after of course) :
export const getRequest = ( endpoint ) => axios
.get( env._URL_SERVER_ + endpoint, { headers: getHeaders() } )
.then((res) => {
// Success
console.log(res);
return {error: false, response: res.data};
})
.catch((error) => {
// Error
if (error.response) {
/*
* The request was made and the server responded with a
* status code that falls out of the range of 2xx
*/
console.log(error.response.data);
console.log(error.response.status);
return {error: true, status: error.response.status, data: error.response.data};
} else if (error.request) {
/*
* The request was made but no response was received, `error.request`
* is an instance of XMLHttpRequest in the browser and an instance
* of http.ClientRequest in Node.js
*/
console.log(error.request);
return {error: true, data: error.request };
} else {
// Something happened in setting up the request and triggered an Error
console.log('Error', error.message);
return {error: true, data: error.message}
}
});
Ant then in my components I do that :
getSchools = () => {
this.setState({
loadingSchools: true
}, () => {
getRequest(`/schools?name=${this.state.filterByName}&city=${this.state.filterByCity}&school_type_id=${this.state.filterBySchoolTypeId}&page=${this.state.selectedPage}`)
.then((response) => {
// there is an error
if (!response.error) {
this.setState({
schools: response.response.data,
meta: response.response.meta,
links: response.response.links
})
} else {
this.setState({
error: true,
errorMessage: response.data,
})
}
})
.then(() => {
this.setState({loadingSchools : false});
})
})
}
It works fine. I tested it in several situation (all is OK - 200, not found - 404, no response). But is it a good practice ? I feel that there is a lot of codes in the parent component. Maybe I complicate my life?
Here is how I've done it:
var URL_BACKEND = "http://localhost:5000/";
// Create Function to handle requests from the backend
callToBackend = async (ENDPOINT, METHOD) => {
const options = {
url: `${URL_BACKEND}${ENDPOINT}`,
method: METHOD,
headers: {
Accept: "application/json",
"Content-Type": "application/json;charset=UTF-8",
},
};
const response = await axios(options);
return response.data;
}
// Then you make a call with the exact endpoint and method:
const response = await this.callToBackend('createSetupIntent', 'POST');
console.log(JSON.stringify(response));
create one common file for base URL let's say api.js
// api.js file code
export const apiUrl = axios.create({
baseURL: 'http://localhost:5000',
});
Register file
// register.js file code
import { apiUrl } from './api';
try {
const resp = await apiUrl.post('/api/register', {
username,
email,
password,
});
const { data, status } = resp;
if (Object.keys(data).length && status === 200) {
// received api data successfully
console.log('API response', data);
}
} catch (err) {
console.log(err);
}
// For auth request
try {
const token = localstorage.getItem('token');
const res = await apiUrl.post(
'/authroute',
{
name: fullName,
originCountry: country,
career: careerStatus,
},
{
headers: { Authorization: `Bearer ${token}` },
}
);
const { data, status } = strapiRes;
if (Object.keys(data).length && status === 200) {
return res.status(status).json(data);
}
} catch (error) {
throw new Error(error);
}
// same for all request
apiUrl.get(endpoint);
apiUrl.post(endpoint, body);
apiUrl.put(endpoint, body);
apiUrl.delete(endpoint, body);
In a simple react set up with express, the very first fetch get request is too slow. The get requests following it seem normal speed.See the first /api/passages/happiness in the log below with a time of 33+ milliseconds.
Basic order of operations:
button click triggers GET request from local Express server
sets state with the data
calls an external API through a proxy url
displays that data in a modal
I'm new at speed/performance issues. Where do I begin troubleshooting? Or which step is likely slowing it down?
// onClick of button, these steps occur:
handleOpen = () => {
// 1. call express api, returns a few lines of text
baseService.get(`/api/passages/${this.props.document}`)
.then(data => {
this.setState({
reference: data.reference,
abbr: data.abbr,
start: data.start,
end: data.end
})
})
.catch(err => {
alert("Verse failed to load")
console.log(err)
})
// 2. call external api, returns a few lines of text
.then(() => {
const url = `https://bibles.org/v2/chapters/eng-NASB:${this.state.abbr}/verses.js?start=${this.state.start}&end=${this.state.end}`
fetch(proxyurl + url, {
headers: new Headers({ 'Authorization': 'Basic ' + window.btoa(`${BIBLE_API_KEY}: x`) }),
redirect: "follow",
})
.then(res => res.json())
.then(contents => {
let versearray = contents.response.verses
versearray.forEach(verse => {
var regex = /(<([^>]+)>)|[0-9]/ig;
let versetext = verse.text.replace(regex, "");
let alltext = this.state.content.concat(' ', versetext)
this.setState({
content: alltext,
// 3. open modal displaying few lines of text
open: true
})
})
})
})
.catch(err => {
alert("Your Verse Failed to Load");
console.log(err)
})
};
config
let mongoose = require('mongoose');
const server = '127.0.0.1:27017'
const database = 'verseapp';
class Database {
constructor() {
this._connect()
}
_connect() {
mongoose.connect(`mongodb://${server}/${database}`, {
useNewUrlParser: true,
useCreateIndex: true,
})
.then(() => {
console.log('Database connection successful')
})
.catch(err => {
console.log('Database connection error', err)
})
}
}
module.exports = new Database()
i am beginner react-native programmer . I am trying to return the responseJSON in a fetch function . I know it is asynchronous and will return promise, thus I need to use .then() , but when it says undefined is not an object.
here is the code
auth.js
export const onVerify = (email,password,navigation) => {
console.log('Verifying');
fetch('xxx',
{
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'email=' + email + '&password=' + password
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.status == '200') {
Alert.alert(
'Login Successful',
'Welcome Home'
);
let data = {
name: responseJson.name,
id : responseJson.id
};
onSignIn();
return responseJson
}
in my signin.js
export default class SignIn extends React.Component{
step(){
onVerify(this.state.email,this.state.password,this.props.navigation).then(
function(data) {
console.log(data);
}
);
}
As said by #teivaz on the comment, your onVerify function returns nothing. Because the fetch call is asynchronous. So what you can do is return a Promise from onVerify then you'll be able to resolve it from step function.
This is how you can implement this,
export const onVerify = (email,password,navigation) => {
return new Promise((resolve, reject) => {
fetch('endpoint',
{
method,
headers,
body,
})
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.status == '200') {
Alert.alert(
'Login Successful',
'Welcome Home'
);
let data = {
name: responseJson.name,
id : responseJson.id
};
onSignIn();
resolve(responseJson)
}
})
.catch(err => reject(err));
}
}
Also, make sure to catch the errors if any in step function.
export default class SignIn extends React.Component{
step(){
onVerify(this.state.email,this.state.password,this.props.navigation).then(
function(data) {
console.log(data);
}
)
.catch(err => console.log('Error occured', err));
}
}