How to use query string in fetch post? - reactjs

Newbie here. Building a React site. I'm struggling to get my authentication to go through a fetch post. It keeps returning "No such user" error, but when I have verified the user DOES exist.
I'm using passport on the backend.
const handleSubmit = (event) => {
event.preventDefault();
const data = {
Username: username,
Password: password
};
fetch('https://cthulhuflix.onrender.com/login', {
method: 'POST',
body: new URLSearchParams(JSON.stringify(data))
})
.then ((response) => response.json())
.then ((data) => {
console.log('Login response: ', data);
if (data.user) {
onLoggedIn(data.user, data.token);
} else {
alert('Dave\'s not here! No such user.');
}
})
.catch((e) => {
alert('Something went wrong');
});
};

Here's what I ended up with:
export const LoginView = ({ onLoggedIn }) => {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const handleSubmit = (event) => {
event.preventDefault();
const data = {
Username: username,
Password: password
};
fetch('https://cthulhuflix.onrender.com/login?' + new URLSearchParams(data).toString(), {
method: 'POST',
body: JSON.stringify(data)
}).then ((response) => {
if (response.ok) {
onLoggedIn(username);
} else {
alert('Login failed');
}
});
};

Related

Authenticate my ReactJS SPA with laravel/sanctum using Axios

After a successful authentication (login + token), I'm still unable to request auth:sanctum routes and I get the following response:
LoginForm component
import React, { useState } from "react";
const LoginForm = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const loginHandler = (ev) => {
ev.preventDefault();
if (email.length > 0 && password.length > 0) {
axios.get("/sanctum/csrf-cookie").then(() => {
axios
.post("api/login", {
email: email,
password: password,
})
.then((response) => {
console.log(response.data);
})
.catch(function (error) {
console.error(error);
});
});
}
};
Login action
public function login(Request $request)
{
$request->validate(['email' => 'required', 'password' => 'required|string']);
$user = User::where('email', $request->email)->first();
if (!$user || !password_verify($request->password, $user->password)) {
return response(['message' => 'Bad credentials'], 401);
}
$token = $user->createToken('token')->plainTextToken;
return response(['user' => $user, 'token' => $token], 201);
}
Login Response
{
"user": {
"id": 7,
"email": "daphne19#example.com",
"email_verified_at": "2022-03-09T16:40:59.000000Z",
"created_at": "2022-03-09T16:40:59.000000Z",
"updated_at": "2022-03-09T16:40:59.000000Z"
},
"token": "5|oCnoaVBBYARcFXwdd7dXegchFLS6fckDgr2Bl0L0"
}
You need to pass Sanctum Token in Axios Header.
first you need to set user response in local storage.
const LoginForm = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const loginHandler = (ev) => {
ev.preventDefault();
if (email.length > 0 && password.length > 0) {
axios.get("/sanctum/csrf-cookie").then(() => {
axios
.post("api/login", {
email: email,
password: password,
})
.then((response) => {
//set response in local storage
localStorage.setItem('user', JSON.stringify(response.data))
})
.catch(function (error) {
console.error(error);
});
});
}
};
then you need to pass token in Axios Header
const user = JSON.parse(localStorage.getItem('user'));
const headers = {
accept: 'application/json',
Authorization: 'bearer ' + user.token
}
//set token in axios header
axios.get(API, {
headers: headers
})
.then((res) => { })
.catch((err) => { })
please change the bearer to Bearer while making an authentication requests using Axios.

how to get user id after token authentication - REACT

I'm new at coding so hoping this is something simple. I am trying to create delete/update functions for the user when they go to their profile. To delete and update my api needs the user id for:
fetch(${process.env.REACT_APP_API_URL}users/${id}/,
Token authentication works and is stored in the localhost but I can't seem to access the id of the user after login. How can I store the id and call it in this function?
**Notes: the 'userData' const was an attempt at calling the api by:
fetch(${process.env.REACT_APP_API_URL}users/${userData.id}/,
(didn't work)
my ProfilePage code:
const Profile = () => {
const [userData, setUserData] = useState({
username: "",
email: "",
password: "",
});
const { id } = useParams();
const navigate = useNavigate();
const EditAccount = () => {
navigate("/edit-account");
};
const addCar = () => {
navigate("/home");
};
useEffect(() => {
fetch(`${process.env.REACT_APP_API_URL}users/${id}/`)
.then((results) => {
console.log("results", results);
return results.json();
})
.then((data) => {
setUserData(data);
});
});
const Logout = () => {
localStorage.clear();
window.location.href = "/";
};
const DeleteUser = async () => {
fetch(`${process.env.REACT_APP_API_URL}users/${id}/`, {
method: "delete",
headers: {
Authorization: `Token ${localStorage.getItem("token")}`,
},
});
navigate("/");
};

Axios PUT Data with Params

My backend API route is /api/updateUser/:id
How am I supposed to POST data into this API? I'm familiar with POST request for non params APIs but this one has an /:id in the route.
Can someone show me an example with this demo code
state = {
username: "random123",
password: "random123",
userid: "qwertyuiop",
};
saveDetails = async () => {
const { username, password, userid } = this.state;
let data = new FormData();
data.append('username',username);
data.append('password',password);
axios
.put(apiEndPoint+'?id='+this.state.userid, data) //this is where I need help
.then(async (response) => {
if (response.data) {
console.log("success");
} else {
console.log("issue");
}
})
.catch((err) => {
console.log("error",err);
});
};
This is the working example for Path Parameter Axios PUT request -
saveDetails = async () => {
const { username, password, userid } = this.state;
axios
.put(apiEndPoint+"updateUser/"+userid, {
username:username,
password:password,
})
.then(async (response) => {
if (response.data) {
console.log("done");
} else {
console.log("error");
}
})
.catch((err) => {
console.log("error",err);
});
};

Values won't update after api call with axios

I'm trying to fetch data with axios using React's useEffect in two steps:
1- Get the access token with a POST request
2- Use the token on another POST request to get the desired data
After the first post request, the response returns as expected, but the state value doesn't update. So it sends undefined as the token for the second request.
const [infos, setInfos] = useState(null)
const [token, setToken] = useState('')
useEffect(() => {
const getToken = async () => {
try {
const response = await axios.post(
'adress',
{
username: 'root',
password: 'i_want_my_token',
}
)
setToken(response.data.access)
} catch (error) {
console.log(error)
}
}
getToken()
const getCatalogo = async () => {
try {
let data = { id: 6 }
let configCatalogo = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
}
const catalogoResponse = await axios
.post(
'adress',
data,
configCatalogo
)
setInfos(res.data)
} catch (error) {
console.log(error) }
}
getCatalogo()
}, [])
Since the function to get/set your token is asynchronous, you need to use two different useEffects: one to fetch the token and one to use that token once it is set.
const [infos, setInfos] = useState(null)
const [token, setToken] = useState('')
useEffect(() => {
const getToken = async () => {
try {
const response = await axios.post(
'adress',
{
username: 'root',
password: 'i_want_my_token',
}
)
setToken(response.data.access)
} catch (error) {
console.log(error)
}
}
getToken()
}, []);
useEffect(() => {
const getCatalogo = async () => {
try {
let data = { id: 6 }
let configCatalogo = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
}
const catalogoResponse = await axios
.post(
'adress',
data,
configCatalogo
)
setInfos(res.data)
} catch (error) {
console.log(error) }
}
getCatalogo()
}, [token]);

called async function from state is not waiting (react)

I call a state function in my component, the function should change the state(and it does but late), i want to log the change but the log triggers before the state is changed
this is the function in the state:
const login = async (user, password) => {
const body = {
username: user,
password: password,
};
await axios
.post('/sessions', body, {
headers: { 'Content-Type': 'application/json' },
})
.then((resp) => {
dispatch({ type: LOGIN, payload: resp.data.data });
})
.catch((err) => {
console.log(err.response.data);
});
};
and this is the call in the component
const onSubmit = (e) => {
e.preventDefault();
login(user, password);
console.log(credes);
};
"credes" is the state for that response, but it keeps printing the initial state witch is an empty object
the function triggers on the form submission but logs first and updates the state later.
As pointed out by bubulledu93, ronakvp and coreyward, I was butchering the syntax. I was trying to perform two actions in one function, so I moved the log into a useEffect to watch for changes in the "credes" hope is the right way but is working as I needed it.
const login = (user, password) => {
const body = {
username: user,
password: password,
};
axios
.post('/sessions', body, {
headers: { 'Content-Type': 'application/json' },
})
.then((resp) => {
dispatch({ type: LOGIN, payload: resp.data });
})
.catch((err) => {
console.log(err.response.data);
});
};
and the call in the component + the useEffect
const onSubmit = (e) => {
e.preventDefault();
login(user, password);
};
useEffect(() => {
if (credes.success) {
console.log(credes.data);
}
}, [credes]);
There isn't any benefit to awaiting as the last call in a function. Instead of using async and await, simply return the Promise chain started by axios.post() to onSubmit and then chain on it (or use await there):
const login = (user, password) => {
const body = {
username: user,
password: password,
};
return axios
.post('/sessions', body, {
headers: { 'Content-Type': 'application/json' },
})
.then((resp) => {
dispatch({ type: LOGIN, payload: resp.data.data });
})
.catch((err) => {
console.log(err.response.data);
});
};
// Option 1:
const onSubmit = (e) => {
e.preventDefault();
login(user, password)
.then(() => {
console.log(credes);
});
};
// Option 2:
const onSubmit = async (e) => {
e.preventDefault();
await login(user, password);
console.log(credes)
}

Resources