Login page verification in reactjs - javascript

I want to translate an angularjs login page to reactjs. I did the code but I want to know if it's the right way to do it and if it's correct till what I have done. Also I want to add the dashboard page which can be accessed only authentication and user will be redirected to dashboard after login.
$scope.login=function(){
$scope.newuser={
'password':$scope.signinpassword,
'email':$scope.emailid
}
return $http.post('/api/authenticate',$scope.newuser).then(function(response,status){
if(response.data=='redirect'){
$window.location.href="/dashboard";
}else if(response.data=='verifyemail'){
angular.element(document.querySelector('#verifyemailbtn')).click();
}else if(response.data=='Invalid Password'){
window.alert("Incorrect Password");
$scope.error='Failed to authenticate'
}
});
}
my reactjs code that I translated so far
class Login extends Component {
constructor(props){
super(props);
this.state={
emailid:'',
password:''
}
}
performLogin = async (event) => {
var body={
"emailid":"this.state.emailid",
"password":"this.state.password"
}
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: body
};
const url = "api/login";
try {
const response = await fetch(url, options);
const result = await response.json();
console.log(`login successful`);
} catch (error) {
console.error("login credentials wrong");
}
};
render() {
return (
<div>
<input type="text"
placeholder="emailid"
onChange = {(event,newValue) => this.setState({emailid:newValue})}
/>
<br/>
<input
type="password"
placeholder="Enter your Password"
onChange = {(event,newValue) => this.setState({password:newValue})}
/>
<br/>
<button type="submit" onClick={(event) => this.performLogin(event)}/>
</div>
);
}
}
export default Login;

your code approaching is ok but have some syntax issues.
1- your need to bind "this" for methods in constructor
2- remove double quotation in performLogin for this.state.emailid
3- you don't need many functions for each input you can just handle all input feilds just with one function like so.
i refactor your code :-)
class Login extends Component {
constructor(props){
super(props);
this.performLogin = this.performLogin.bind(this)
this.handleChange = this.handleChange.bind(this)
this.state={
emailid:'',
password:''
}
}
performLogin = async (event) => {
const { enteredText } = this.state;
var body={
"emailid":this.state.emailid,
"password":this.state.password
}
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: body
};
const url = "api/login";
try {
const response = await fetch(url, options);
const result = await response.json();
$window.location.href="/dashboard";
} catch (error) {
console.error("login credentials wrong");
}
};
handleChange(e) {
this.setState({[e.target.name]:e.target.value})
}
render() {
return (
<div>
<input type="text"
placeholder="emailid"
onChange = {handleChange}
/>
<br/>
<input
type="password"
placeholder="Enter your Password"
onChange = {handleChange}
/>
<br/>
<button type="submit" onClick={this.performLogin}/>
</div>
);
}
}
export default Login;
for redirecting you can use lib like React-Router or just replace console.log(login successful) with $window.location.href="/dashboard"

Related

How correctly send data from forms to my URL?

How to read data from this forms and send it to my custom URL?
<div className='contact-form-group'>
<InputGroup size="small">
<input type="text"
placeholder={'Enter Your Name'}/>
</InputGroup>
</div>
<InputGroupAddon addonType="append">
<div className="contact-search-icon-container">
submit
</div>
</InputGroupAddon>
my_url works like an echo: what you sent, you will receive in text form
handleSubmit = (event) => {
event.preventDefault()
const form = event.target
const data = new FormData(form)
for (let name of data.keys()) {
const input = form.elements[name]
}
const proxyUrl = 'https://cors-anywhere.herokuapp.com/'
const url = 'my_url'
fetch(proxyUrl + url, {
method: 'POST',
body: data,
headers: { 'Content-Type': 'application/json' },
}).then(function (response) {
//handle success
console.log(response)
})
.catch(() => console.log('Can’t access ' + url + ' response. Blocked by browser?'))
}
You don't need to pass event.target to FormData I think.
Here's a simple solution that shows how to handle files as well as text:
import React from "react";
class Upload extends React.Component {
constructor() {
super();
this.state = {
image: ""
};
}
handleFileChange = e => {
this.setState({
[e.target.name]: e.target.files[0]
});
};
handleTextChange = e => {
this.setState({
[e.target.name]: e.target.value
});
};
handleSubmit = async e => {
e.preventDefault();
const formData = new FormData();
for (let name in this.state) {
formData.append(name, this.state[name]);
}
await fetch("/api/upload", {
method: "POST",
body: formData
});
alert("done");
};
render() {
return (
<form onSubmit={this.handleSubmit}>
<input name="image" type="file" onChange={this.handleFileChange} />
<input name="name" type="text" onChange={this.handleTextChange} />
<input type="submit" />
</form>
);
}
}
export default Upload;

axios request to DRF with JWT auth fails

I have a Django rest API with JWT auth for signup and login built with react.
When trying to log in a user I get a 403 forbidden error.
I added the csrf token to the headers of the request and I can see it in the promise when using the console, so that's not the problem here.
I just don't understand where this post is breaking
import axios from "axios";
import Cookies from "js-cookie";
var csrftoken = Cookies.get("csrftoken");
const axiosInstance = axios.create({
baseURL: "http://127.0.0.1:8000/api/",
timeout: 5000,
headers: {
HTTP_X_CSRF_TOKEN: csrftoken,
Authorization: localStorage.getItem("access_token")
? "JWT " + localStorage.getItem("access_token")
: null,
"Content-Type": "application/json",
accept: "application/json",
withCredentials: true,
},
});
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
const originalRequest = error.config;
// test for token presence, no point in sending a request if token isn't present
if (
localStorage.getItem("refresh_token") &&
error.response.status === 401 &&
error.response.statusText === "Unauthorized"
) {
const refresh_token = localStorage.getItem("refresh_token");
return axiosInstance
.post("/token/refresh/", { refresh: refresh_token })
.then((response) => {
localStorage.setItem("access_token", response.data.access);
localStorage.setItem("refresh_token", response.data.refresh);
axiosInstance.defaults.headers["Authorization"] =
"JWT " + response.data.access;
originalRequest.headers["Authorization"] =
"JWT " + response.data.access;
return axiosInstance(originalRequest);
})
.catch((err) => {
console.log(err);
});
}
// specific error handling done elsewhere
return Promise.reject({ ...error });
}
);
export default axiosInstance;
And the login component using the axios instance:
import React, { Component } from "react";
import axiosInstance from "../axiosApi";
import DjangoCSRFToken from "django-react-csrftoken";
class Login extends Component {
constructor(props) {
super(props);
this.state = { username: "", password: "" };
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({ [event.target.name]: event.target.value });
}
async handleSubmit(event) {
event.preventDefault();
try {
const response = await axiosInstance.post("/token/obtain/", {
username: this.state.username,
password: this.state.password,
});
axiosInstance.defaults.headers["Authorization"] =
"JWT " + response.data.access;
localStorage.setItem("access_token", response.data.access);
localStorage.setItem("refresh_token", response.data.refresh);
return response;
} catch (error) {
throw error;
}
}
render() {
return (
<div>
Login
<form onSubmit={this.handleSubmit}>
<DjangoCSRFToken />
<label>
Username:
<input
name="username"
type="text"
value={this.state.username}
onChange={this.handleChange}
/>
</label>
<label>
Password:
<input
name="password"
type="password"
value={this.state.password}
onChange={this.handleChange}
/>
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
}
export default Login;
the console when hitting submit:
Please try removing CSRF from the call. and make use of #csrf_exepmt for further information please follow this link. Django csrf_exempt using your JWT it's enough.
Example:
#csrf_exempt
def myEndpoint():
// my code

How to make Post Request using ReactJS

Hi I am student developer at ReactJS. I am trying to learn how to code with Reactjs Context Api. When I send a data from my form for categories, I am facing an error like this
Unhandled Rejection (TypeError): Failed to execute 'fetch' on
'Window': Request with GET/HEAD method cannot have body.
What is the meaning of this? What i am mising when I do this process? Fallowing code includes my methods.
my context part :
import React, { Component } from 'react';
const CapsuleContext = React.createContext();
const reducer = (state,action)=>{
switch (action.type) {
case "SAVE_CATEGORY_TO_API":
fetch("http://localhost:3000/categories/", {
headers: { "content-type": "application/json",
"Accept":"application/json" },
body: JSON.stringify(action.payload)
})
break;
default:
return state
}
}
export class CapsuleProvider extends Component {
state = {
categories: [],
apiUrl: "http://localhost:3000/",
dispatch : action => {
this.setState(state => reducer(state,action))
}
}
getCategories = () => {
fetch(this.state.apiUrl + "categories")
.then(res => res.json())
.then(data => this.setState({ categories: data }));
}
render() {
return (
<CapsuleContext.Provider value = {this.state}>
{this.props.children}
</CapsuleContext.Provider>
);
}
}
const CapsuleConsumer = CapsuleContext.Consumer;
export default CapsuleConsumer;
my categoryAdd component :
import React, { Component } from 'react';
import { Button, Form, FormGroup, Label, Input, ListGroup, ListGroupItem } from 'reactstrap';
import { Link } from "react-router-dom"
import CapsuleConsumer from '../../context/Context';
import CategoryList from './CategoryList';
class CategoryAdd extends Component {
handleChange = (event) => {
let value = event.target.value;
let name = event.target.name;
this.setState({ [name]: value })
}
handleSubmit = (event) => {
event.preventDefault();
}
saveCategory = (event, dispatch) => {
dispatch({ type: "SAVE_CATEGORY_TO_API", payload: {id : event.state.id , categoryName : event.state.categoryName , seoUrl:event.state.seoUrl}})
}
render() {
return (
<CapsuleConsumer>
{
value => {
const { categories, dispatch } = value;
return (
<div>
<div>
<Form className="mt-3 font-weight-bold" onSubmit={this.handleSubmit}>
<FormGroup className="text-left">
<Label for="id">Category Id</Label>
<Input type="text"
name="id"
onChange={this.handleChange}
placeholder={categories.length + 1}
/>
</FormGroup>
<FormGroup className="text-left">
<Label for="categoryName">Category Name</Label>
<Input type="text"
name="categoryName"
onChange={this.handleChange}
placeholder="enter a category name" />
</FormGroup>
<FormGroup className="text-left">
<Label for="seoUrl">Seo Url</Label>
<Input type="text"
name="seoUrl"
onChange={this.handleChange}
placeholder="enter a seo url" />
</FormGroup>
<Button color="success" onClick={() => this.saveCategory(this, dispatch)} type="submit">Submit</Button>
</Form>
</div>
</div>
)
}}
</CapsuleConsumer>
);
}
}
export default CategoryAdd;
The reason for your error is because fetch sends a GET request by default which does not allow a body as part of the request. You need to specify that the fetch method is POST:
fetch("http://localhost:3000/categories/", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Accept":"application/json"
},
body: JSON.stringify(action.payload)
})
You are sending a GET type request and this method does not use body like POST or PATCH...
Please check your code at
fetch("http://localhost:3000/categories/", {
headers: { "content-type": "application/json",
"Accept":"application/json" },
body: JSON.stringify(action.payload)
})
if you are going to send something using GET must send it in the URL

TypeError: Failed to fetch in reactjs login page

I've been trying to create a login page but I'm getting this error called "TypeError: Failed to fetch". I have no idea where I did wrong, I checked a few StackOverflow answers, like I tried adding the event.preventdefault as I saw in one of StackOverflow answer but that didn't help.
Could someone point out the part where I'm doing wrong?
Also note: it's working fine in postman with the API. I tried the same email and password there and it's working fine in postman but getting the error with the react website.
import React, { Component } from "react";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
this.onchange = this.onchange.bind(this);
}
onchange(e) {
this.setState({ [e.target.name]: e.target.value });
console.log(this.state);
}
performLogin = async event => {
event.preventDefault();
console.log("button clicked");
var body = {
password: "this.state.password",
email: "this.state.email"
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(body)
};
const url = "/api/authenticate";
try {
const response = await fetch(url, options);
const result = await response.json();
console.log(result);
console.log(`login successful`);
window.alert("login succesful");
} catch (error) {
console.error(error);
}
};
render() {
return (
<div>
<input type="text" placeholder="emailid" onChange={this.onchange} />
<br />
<input
type="password"
placeholder="Enter your Password"
onChange={this.onchange}
/>
<br />
<button type="submit" onClick={event => this.performLogin(event)}>
Submit
</button>
</div>
);
}
}
export default Login;
one anamoly is that in postman, it accepts only when I post like I've shown below
{
"password":"pass",
"email":"admin"
}
If I remove the quotes then it gives me bad string error in postman
but in codesandbox, the quotes are automatically removed when I save the sandbox. could it be because of that or is it nothing to worry about?
First you need to give your inputs name attribute to be able to correctly update the state onChange like this:
<input type="text" name="email" placeholder="emailid" onChange={this.onchange} /> <br />
<input type="password" name="password" placeholder="Enter your Password" onChange={this.onchange}/>
Secondly, you need to create the request body like this:
var body = {
password: this.state.password,
email: this.state.email
};
And lastly, you need to check if fetch response is ok, because in 4xx errors fetch does not give error.
So with all these changes, your component code must be like this:
import React, { Component } from "react";
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: "",
password: ""
};
this.onchange = this.onchange.bind(this);
}
onchange(e) {
this.setState({ [e.target.name]: e.target.value });
}
performLogin = async event => {
event.preventDefault();
var body = {
password: this.state.password,
email: this.state.email
};
const options = {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json"
},
body: JSON.stringify(body)
};
const url = "/api/authenticate";
try {
const response = await fetch(url, options);
const result = await response.json();
console.log(result);
if (response.ok) {
console.log("login successful");
window.alert("login succesful");
} else {
console.log("login failed");
window.alert("login failed");
}
} catch (error) {
console.error(error);
}
};
render() {
return (
<div>
<input
type="text"
name="email"
placeholder="emailid"
onChange={this.onchange}
/>
<br />
<input
type="password"
name="password"
placeholder="Enter your Password"
onChange={this.onchange}
/>
<br />
<button type="submit" onClick={event => this.performLogin(event)}>
Submit
</button>
<hr />
State: {JSON.stringify(this.state)}
</div>
);
}
}
export default Login;
But these fixes in react app will not be enough, because codesandbox uses https and login api is using http. This will give the following error:
Mixed Content: The page at 'https://hkj22.csb.app/Login' was loaded
over HTTPS, but requested an insecure resource
'http://***/api/authenticate'. This request has been
blocked; the content must be served over HTTPS.
And only way to resolve this problem seems to use https for the api as described in this answer.
You can contact api owner to host his api using https.

Request received always is empty

I'm working with react, redux-form and laravel.
I have created a form to be able to insert notes in the database but when I show the Request in laravel an empty array always appears.
I do not know what I'm doing wrong.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
notes: [],
};
this.submitToServer = this.submitToServer.bind(this)
this.submit = this.submit.bind(this)
}
componentWillMount() {
fetch('http://127.0.0.1:8000/notes')
.then(res => res.json())
.then(json => json.results)
.then(notes => this.setState({ notes }))
.catch(console.log)
}
async submitToServer(data) {
let response = await fetch('http://127.0.0.1:8000/notes', {
method: "POST",
headers: {
'Accept': 'application/json',
'Content-type': 'application/json',
},
body: JSON.stringify(data)
})
let responseJSON = await response.json()
return responseJSON
}
submit({ title, content }) {
this.submitToServer({ title, content })
.then(res => this.setState(prevState => ({
notes: [...prevState.notes, {
id: prevState.notes.pop().id + 1,
title: title,
content: content
}]
})))
}
render() {
if (this.state.notes.length > 0) {
return (
<div>
<h1>Notas</h1>
<Paper>
<form onSubmit={this.props.handleSubmit(this.submit)}>
<Field name="title" label="Title" component={renderField} type="text" />
<Field name="content" label='Content' component={renderField} type="text" />
<button type="submit">Submit</button>
</form>
</Paper>
))}
</div>
)
} else {
return <p>Cargando notas...</p>
}
}
}
In laravel at the moment I'm just returning the Request to show what it contains.
public function storeNote(Request $request) {
return $request;
}

Categories