Related
I'm working with React Redux, and I'm trying to call a function inside another function on my actions file. The problem is It only work if I take the dispatch part of the function.
I wan't to call updateToken() from askForUser() but it will only work if I take the dispatch part from updateToken(). Also when i call askForUser() from askForUser() it won't work either.
const updateToken = (token) => dispatch => {
console.log(token)
dispatch({
type: UPDATE_TOKEN,
payload: token
})
}
const askForUser = (token) => dispatch => {
dispatch({ type: ASKING_FOR_DATA })
axios.get(API.GET_USER, {
params: {
token
}
}).then((response) => {
if (response.data.status === 1) {
dispatch({ type: ASK_FOR_USER, payload: response.data.user })
} else if (response.data.status === 2) {
updateToken(response.data.token)
//console.log(hola2())
} else {
NotificationManager.error('Error consiguiendo usuario')
dispatch({ type: ERROR_HANDLER })
}
}).catch((err) => {
console.log(err)
dispatch({ type: ERROR_HANDLER })
})
}
you'll have to dispatch it :
else if (response.data.status === 2) {
dispatch(updateToken(response.data.token)); // dispatch the function here
}
I have read articles that saving the token in localstorage is dangerous to XSS attack. So I have decided to store my tokens in cookies. And I am using react-cookie. I saw the examples and I am trying to do it but my auth.js consists of const and is not a class, so I do not know how to use the withCookies() with it, this is my auth.js where I want to store the token to the cookies:
import {
LOGIN,
LOGIN_SUCCESS,
LOGIN_FAILED,
GET_USER_DATA,
GET_USER_DATA_SUCCESS,
GET_USER_DATA_FAILED,
LOGOUT,
LOGOUT_SUCCESS,
LOGOUT_FAILED,
} from './types'
import axios from 'axios'
var api = require ('./../api.js');
export const login = (email, pass) => {
return (dispatch) => {
dispatch({
type: LOGIN
})
var url = api.logInApi
axios.post(url, {
email: email,
password: pass
})
.then(res => {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
localStorage.setItem('token', res.data.token)
dispatch(getUserData())
})
.catch(err => dispatch({
type: LOGIN_FAILED,
payload: err
}))
}
}
export const getUserData = () => {
return (dispatch) => {
dispatch({
type: GET_USER_DATA
})
var url = api.getUserDataApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${localStorage.getItem("token")}`
}})
.then(res => {
dispatch({
type: GET_USER_DATA_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: GET_USER_DATA_FAILED,
payload: err
}))
}
}
export const logout = () => {
return (dispatch) => {
dispatch({
type: LOGOUT
})
var url = api.logoutApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${localStorage.getItem("token")}`
}})
.then(res => {
window.location.replace("")
dispatch({
type: LOGOUT_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: LOGOUT_FAILED,
payload: err
}))
}
}
Now, I tried doing this and of course it doesn't work:
import {
LOGIN,
LOGIN_SUCCESS,
LOGIN_FAILED,
GET_USER_DATA,
GET_USER_DATA_SUCCESS,
GET_USER_DATA_FAILED,
LOGOUT,
LOGOUT_SUCCESS,
LOGOUT_FAILED,
} from './types'
import axios from 'axios'
import { withCookies, Cookies } from 'react-cookie'; <<added this
var api = require ('./../api.js');
const login = (email, pass) => {
return (dispatch) => {
dispatch({
type: LOGIN
})
const { cookies } = props; <<added this
var url = api.logInApi
axios.post(url, {
email: email,
password: pass
})
.then(res => {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
cookies.set('token', res.data.token, { path: '/' }); <<added this
dispatch(getUserData())
})
.catch(err => dispatch({
type: LOGIN_FAILED,
payload: err
}))
}
}
export default withCookies(login) <<added this(wrong)
const getUserData = () => {
return (dispatch) => {
dispatch({
type: GET_USER_DATA
})
const { cookies } = props; <<added this
var token = cookies.get('token'); <<added this
var url = api.getUserDataApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${token}` <<added this(this is where I wanna get the cookie)
}})
.then(res => {
dispatch({
type: GET_USER_DATA_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: GET_USER_DATA_FAILED,
payload: err
}))
}
}
export default withCookies(getUserData) <<added this(wrong)
const logout = () => {
return (dispatch) => {
dispatch({
type: LOGOUT
})
const { cookies } = props;
var token = cookies.get('token');
var url = api.logoutApi
axios.post(url, {}, {headers: {
"Authorization": `Bearer ${token}` <<added this
}})
.then(res => {
window.location.replace("")
dispatch({
type: LOGOUT_SUCCESS,
payload: res.data
})
})
.catch(err => dispatch({
type: LOGOUT_FAILED,
payload: err
}))
}
}
export default withCookies(logout) <<added this(wrong)
this one is wrong because there should only be one export default. But I don't know how to implement withCookies to const and there are also these ones that are included in the example and I don't know if I need them or where do I put them:
static propTypes = {
cookies: instanceOf(Cookies).isRequired
};
constructor(props) {
super(props);
const { cookies } = props;
this.state = {
name: cookies.get('name') || 'Ben'
};
}
and also, another question is that, I can access my cookies anywhere in my project right? just like how localstorage is accessible to my project?
I hope someone can help me and I am a newbie to this. I have never used cookies before so thank you for your consideration.
I personally would rather using js-cookie to write/read cookies.
It has a very basic API:
Cookie.set('cookie_name', 'value') // will set "cookie_name" to "value"
Cookie.get('cookie_name') // will return "value"
Which means:
const login = (email, pass, cookie) => {
return (dispatch) => {
dispatch({
type: LOGIN
})
var url = api.logInApi
axios.post(url, {
email: email,
password: pass
})
.then(res => {
dispatch({
type: LOGIN_SUCCESS,
payload: res.data
})
cookies.set('token', res.data.token);
dispatch(getUserData())
})
.catch(err => dispatch({
type: LOGIN_FAILED,
payload: err
}))
}
}
Passing to the login funuction js-cookie's Cookie in the 3rd argument.
Now, you can still use the same react-cookie package to read the cookie values (I believe there shouldn't be any conflicts). Or you can replace it with js-cookie. To do that, however, you will have to pass the Cookie object to props. I probably would do that using mapStateToProps if you're using Redux or just by simply passing it through JSX
New to this.
...and this is probably very simple. I have looked at the code for the const "selectData" and I cannot find where a comma is suppose to go. Here is the entire file:
export const requestLoginToken = (username, password) =>
(dispatch, getState) => {
dispatch({ type: REQUEST_LOGIN_TOKEN, payload: username })
const payload = {
userName: username,
password: password,
}
const task = fetch('/api/jwt', {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
})
.then(handleErrors)
.then(response => response.json())
.then(data => {
dispatch({ type: RECEIVE_LOGIN_TOKEN, payload: data })
saveJwt(data)
selectData()
})
.catch(error => {
clearJwt()
dispatch({ type: ERROR_LOGIN_TOKEN, payload: error.message })
})
addTask(task)
return task
}
const selectData = () => {
dispatch({ type: REQUEST_SELECT_DATA })
const token = jwt.access_token
const headers = new Headers({
'Authorization': `Bearer ${token}`
})
const selectData = fetch('/api/SelectData/SelectData', {
method: 'GET',
headers,
})
.then(handleErrors)
.then(response => response.json())
.then(data => {
dispatch({ type: RECEIVE_SELECT_DATA, payload: data })
.catch(error => {
clearJwt()
dispatch({ type: ERROR_SELECT_DATA, payload: error.message })
})
}
}
The error is on the very last curly bracket and it says:
Unexpected token, expected , (72:0)
line 72 is the last curly bracket.
If I remove the const expression that is "selectData" its OK - no errors. The error only appears when I add in that block of code... i.e its in the following:
const selectData = () => {
dispatch({ type: REQUEST_SELECT_DATA })
const token = jwt.access_token
const headers = new Headers({
'Authorization': `Bearer ${token}`
})
const selectData = fetch('/api/SelectData/SelectData', {
method: 'GET',
headers,
})
.then(handleErrors)
.then(response => response.json())
.then(data => {
dispatch({ type: RECEIVE_SELECT_DATA, payload: data })
.catch(error => {
clearJwt()
dispatch({ type: ERROR_SELECT_DATA, payload: error.message })
})
}
}
Why is this block of code causeing an error?
You forgot a ) on the last then:
.then(data => {
dispatch({ type: RECEIVE_SELECT_DATA, payload: data })
.catch(error => {
clearJwt()
dispatch({ type: ERROR_SELECT_DATA, payload: error.message })
})
}) // <--- here
And you should always use ;. I recommend you to use a linter to check your code, like ESLint
Had a look for this in the questions that offered but this was the closest and it didnt really address my problem.
I have a code block (detailed a little way down the page) as part of a larger fetch block.. it gets to this codeblock and also runs fine if this code block is commented out i.e it carrys out a successful fetch etc and returns a JWT no problem but... add this block in and i get the following error:
TypeError: (0 , _localStorageDropDowns.confirmSelectDataExistance)(...).then is not a function
It is referring to this function in another folder (imported correctly)..
export const confirmSelectDataExistance = () => {
const companyStateShortNameJson = localStorage.getItem(COMPANYSTATESHORTNAME)
const statesJson = localStorage.getItem(STATES)
const suburbLocationsJson = localStorage.getItem(LOCATIONS)
if (companyStateShortNameJson || statesJson || suburbLocationsJson) {
console.log('something exists in localstorage')
return true
}
console.log('nothing in localstorage')
return false
}
simple function - returns true or false.
and here is the code block -its failing on the first line:
return confirmSelectDataExistance().then(isConfirmed => {
if (!isConfirmed) {
dispatch({ type: REQUEST_SELECT_DATA })
console.log('gets here!', isConfirmed)
const token = getJwt()
const headers = new Headers({
'Authorization': `Bearer ${token}`
})
const retrieveSelectData = fetch('/api/SelectData/SelectData', {
method: 'GET',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
})
.then(handleErrors)
.then(response => response.json())
.then(selectData => {
dispatch({ type: RECEIVE_SELECT_DATA, payload: selectData })
saveSelectData(selectData)
});
return saveSelectData(selectData);
}
})
From my limited experience the "confirmSelectDataExistance" is a function so why is it saying that its not?
Finally here is the whole action in its entirety so you can see how it that block is called.. as I said - comment the block out and it works perfectly..
export const requestLoginToken = (username, password) =>
(dispatch, getState) => {
dispatch({ type: REQUEST_LOGIN_TOKEN, payload: username })
const payload = {
userName: username,
password: password,
}
const task = fetch('/api/jwt', {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
})
.then(handleErrors)
.then(response => response.json())
.then(data => {
dispatch({ type: RECEIVE_LOGIN_TOKEN, payload: data })
saveJwt(data)
return confirmSelectDataExistance().then(isConfirmed => {
if (!isConfirmed) {
dispatch({ type: REQUEST_SELECT_DATA })
console.log('gets here!', isConfirmed)
const token = getJwt()
const headers = new Headers({
'Authorization': `Bearer ${token}`
})
const retrieveSelectData = fetch('/api/SelectData/SelectData', {
method: 'GET',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
})
.then(handleErrors)
.then(response => response.json())
.then(selectData => {
dispatch({ type: RECEIVE_SELECT_DATA, payload: selectData })
saveSelectData(selectData)
});
return saveSelectData(selectData);
}
})
})
.catch(error => {
clearJwt()
console.log('ERROR - LOGIN!',error)
})
addTask(task)
return task
}
EDIT
I have finally got this to work after hacking away for hours.. Here is the finished action:
export const requestLoginToken = (username, password) =>
(dispatch, getState) => {
dispatch({ type: REQUEST_LOGIN_TOKEN, payload: username })
const payload = {
userName: username,
password: password,
}
const task = fetch('/api/jwt', {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
})
.then(handleErrors)
.then(response => response.json())
.then(data => {
dispatch({ type: RECEIVE_LOGIN_TOKEN, payload: data })
saveJwt(data)
// Now check local storage for dropdown data..
if (!confirmSelectDataExistance()) {
dispatch({ type: REQUEST_SELECT_DATA })
const token = JSON.stringify(data)
const headers = new Headers({
'Authorization': `Bearer ${token}`
})
const retrieveSelectData = fetch('/api/SelectData/SelectData', {
method: 'GET',
headers: {
'Content-Type': 'application/json;charset=UTF-8'
},
})
.then(handleErrors)
.then(response => response.json())
.then(selectData => {
dispatch({ type: RECEIVE_SELECT_DATA, payload: selectData })
saveSelectData(selectData)
});
}
})
.catch(error => {
clearJwt()
console.log('ERROR - LOGIN!', error)
})
addTask(task)
return task
}
and here is the function it calls:
export const confirmSelectDataExistance = () => {
const companyStateShortNameJson = localStorage.getItem(COMPANYSTATESHORTNAME)
const statesJson = localStorage.getItem(STATES)
const suburbLocationsJson = localStorage.getItem(LOCATIONS)
if (companyStateShortNameJson || statesJson || suburbLocationsJson) {
console.log('something exists in localstorage')
return true
}
console.log('nothing in localstorage')
return false
}
The one thing I changed from the other attempts is that I used "data" instead of calling "getJwt()". I then used the line:
const token = JSON.stringify(data)
to obtain the JWT I just got.
In the end I used #Karin s answer and ran with that. (upvoted by me)
The error is not saying that confirmSelectDataExistance is not a function, it's saying that then isn't a function on what is returned from it, which is a boolean (it would be equivalent to false.then(...), which doesn't work).
If seems like you're trying to use then as a conditional. In that case a simple if statement should work:
if (confirmSelectDataExistance()) {
// do things if it returns true
} else {
// do things if it returns false
}
export const confirmSelectDataExistance = () => {
return new Promise(function (resolve, reject) {
const companyStateShortNameJson = localStorage.getItem(COMPANYSTATESHORTNAME)
const statesJson = localStorage.getItem(STATES)
const suburbLocationsJson = localStorage.getItem(LOCATIONS)
if (companyStateShortNameJson || statesJson || suburbLocationsJson) {
console.log('something exists in localstorage')
resolve(true)
}
console.log('nothing in localstorage')
reject(false)
})
}
Try something like this:
export const confirmSelectDataExistance = new Promise((resolve, reject) => {
const companyStateShortNameJson = localStorage.getItem(COMPANYSTATESHORTNAME);
const statesJson = localStorage.getItem(STATES);
const suburbLocationsJson = localStorage.getItem(LOCATIONS);
if (companyStateShortNameJson || statesJson || suburbLocationsJson) {
console.log('something exists in localstorage');
resolve(true);
}
console.log('nothing in localstorage');
reject(false); // or resolve(false) if you want handle this situation inside then block also
});
I have gotten outside of GET and POST methods with Fetch. But I couldn't find any good DELETE and PUT example.
So, I ask you for it. Could you give a good example of DELETE and PUT methods with fetch. And explain it a little bit.
Here is a fetch POST example. You can do the same for DELETE.
function createNewProfile(profile) {
const formData = new FormData();
formData.append('first_name', profile.firstName);
formData.append('last_name', profile.lastName);
formData.append('email', profile.email);
return fetch('http://example.com/api/v1/registration', {
method: 'POST',
body: formData
}).then(response => response.json())
}
createNewProfile(profile)
.then((json) => {
// handle success
})
.catch(error => error);
Ok, here is a fetch DELETE example too:
fetch('https://example.com/delete-item/' + id, {
method: 'DELETE',
})
.then(res => res.text()) // or res.json()
.then(res => console.log(res))
For put method we have:
const putMethod = {
method: 'PUT', // Method itself
headers: {
'Content-type': 'application/json; charset=UTF-8' // Indicates the content
},
body: JSON.stringify(someData) // We send data in JSON format
}
// make the HTTP put request using fetch api
fetch(url, putMethod)
.then(response => response.json())
.then(data => console.log(data)) // Manipulate the data retrieved back, if we want to do something with it
.catch(err => console.log(err)) // Do something with the error
Example for someData, we can have some input fields or whatever you need:
const someData = {
title: document.querySelector(TitleInput).value,
body: document.querySelector(BodyInput).value
}
And in our data base will have this in json format:
{
"posts": [
"id": 1,
"title": "Some Title", // what we typed in the title input field
"body": "Some Body", // what we typed in the body input field
]
}
For delete method we have:
const deleteMethod = {
method: 'DELETE', // Method itself
headers: {
'Content-type': 'application/json; charset=UTF-8' // Indicates the content
},
// No need to have body, because we don't send nothing to the server.
}
// Make the HTTP Delete call using fetch api
fetch(url, deleteMethod)
.then(response => response.json())
.then(data => console.log(data)) // Manipulate the data retrieved back, if we want to do something with it
.catch(err => console.log(err)) // Do something with the error
In the url we need to type the id of the of deletion: https://www.someapi/id
Just Simple Answer.
FETCH DELETE
function deleteData(item, url) {
return fetch(url + '/' + item, {
method: 'delete'
})
.then(response => response.json());
}
Here is good example of the CRUD operation using fetch API:
“A practical ES6 guide on how to perform HTTP requests using the Fetch API” by Dler Ari https://link.medium.com/4ZvwCordCW
Here is the sample code I tried for PATCH or PUT
function update(id, data){
fetch(apiUrl + "/" + id, {
method: 'PATCH',
body: JSON.stringify({
data
})
}).then((response) => {
response.json().then((response) => {
console.log(response);
})
}).catch(err => {
console.error(err)
})
For DELETE:
function remove(id){
fetch(apiUrl + "/" + id, {
method: 'DELETE'
}).then(() => {
console.log('removed');
}).catch(err => {
console.error(err)
});
For more info visit Using Fetch - Web APIs | MDN https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch > Fetch_API.
Some examples:
async function loadItems() {
try {
let response = await fetch(`https://url/${AppID}`);
let result = await response.json();
return result;
} catch (err) {
}
}
async function addItem(item) {
try {
let response = await fetch("https://url", {
method: "POST",
body: JSON.stringify({
AppId: appId,
Key: item,
Value: item,
someBoolean: false,
}),
headers: {
"Content-Type": "application/json",
},
});
let result = await response.json();
return result;
} catch (err) {
}
}
async function removeItem(id) {
try {
let response = await fetch(`https://url/${id}`, {
method: "DELETE",
});
} catch (err) {
}
}
async function updateItem(item) {
try {
let response = await fetch(`https://url/${item.id}`, {
method: "PUT",
body: JSON.stringify(todo),
headers: {
"Content-Type": "application/json",
},
});
} catch (err) {
}
}
Let me simplify this, you can straight up copy the code.
This is for PUT method :
fetch('https://reqres.in/api/users', + id {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'user'
})
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
and this is for DELETE :
fetch('https://reqres.in/api/users' + id, {
method: 'DELETE',
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
Note: I'm using dummy api here.
This is what worked for me when using the PUT method. This method allows me to effectively update the 1st item using my first name:
fetch('https://reqres.in/api/users', {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
id: 1,
first_name: 'Anthony'
})
})
.then(res => {
return res.json()
})
.then(data => console.log(data))
Here are examples for Delete and Put for React & redux & ReduxThunk with Firebase:
Update (PUT):
export const updateProduct = (id, title, description, imageUrl) => {
await fetch(`https://FirebaseProjectName.firebaseio.com/products/${id}.json`, {
method: "PATCH",
header: {
"Content-Type": "application/json",
},
body: JSON.stringify({
title,
description,
imageUrl,
}),
});
dispatch({
type: "UPDATE_PRODUCT",
pid: id,
productData: {
title,
description,
imageUrl,
},
});
};
};
Delete:
export const deleteProduct = (ProductId) => {
return async (dispatch) => {
await fetch(
`https://FirebaseProjectName.firebaseio.com/products/${ProductId}.json`,
{
method: "DELETE",
}
);
dispatch({
type: "DELETE_PRODUCT",
pid: ProductId,
});
};
};
const DeleteBtn = (id) => {
fetch(`http://localhost:8000/blogs/${id}`, {
method: "DELETE"
})
.then(() => {
navigate('/');
});
}
<button onClick={(event) => { DeleteBtn(blog.id)} }>delete</button>