I use MERN stack and redux. I have two problem and please help me.
1) Every component react I add this:
const user = useSelector( state => state.user );
useEffect( ()=>{
dispatch(User_Auth(12)) ; // I write 12 for action work.
});
I want to get user data every time if user loginned or not. Is it true? or some idea have?
2) In backend if data current I send using 200 status codes. another variant I send data other status like this:
router.get('/auth', (req, res) => {
if(req.isAuthenticated()){
req.user.isAuth = true;
res.status(200).json(req.user);
}
else{
return res.status(401).json({
isAuth: false
});
}
});
This is my action get User data:
export const User_Auth = (value) => async (dispatch) => {
value = value + 0;
await axios({
method: "GET",
url:'http://localhost:3001/api/users/auth',
withCredentials:true
})
.then(res => {
dispatch({type: user_auth, payload: res.data});
}).catch(error => {
// console.log("Auth geldim: ", error);
});
}
I want if cannot see errors in console.log browser. Can I do that?
Thanks
If you want to see the status code from an error you have to access it like this
error.status
And to get the message
error.message
Related
So on my listPage, I have 2 documents, where I want to be able to click the edit button, and it takes me to the editPage. It does do that right now. but what I have it doing, is making the request through an axios.post, so that it sends the id of the document to the backend, and then sends the results to the front end, where it'll only display the one document according to it's id. here's what I have:
listPage:
const editById = (id) => {
console.log(id);
axios
.post(`/getDocToEdit`, { id: id })
.then(() => {
console.log(id, " worked");
window.location = "/admin/services/:site";
})
.catch((error) => {
// Handle the errors here
console.log(error);
});
};
then it hits this backend route:
app.post('/getDocToEdit', (req, res) => {
var id = req.body.id;
ServicesModel.findOne({_id: id}, function(err,result) {
console.log(result);
res.status(200).send(result)
});
})
then I am just trying to display the document on screen in my editPage, but it doesn't load the result that I am sending through res.status(200).send(result). I have just a table that is supposed to show the record. am I supposed to be doing a call from the front end again or something?
you should save post result in your frontend:
const editById = (id) => {
console.log(id);
axios
.post(`/getDocToEdit`, { id: id })
.then((RESPONSE) => {
console.log(RESPONSE); // do it and if you have the response, everything
is fine and you can use it as the returned data
console.log(id, " worked");
window.location = "/admin/services/:site";
})
.catch((error) => {
// Handle the errors here
console.log(error);
});
I'm trying to make an api call that allows me to edit a single user. The issue that I'm experiencing is that despite the call being successful (and no errors appearing), the changes are not saving. Can someone kindly guide me as to what I'm doing wrong exactly, please? I feel that I'm missing a function that allows me to save the changes after I make the call, but I'm not entirely sure how to go about this.
Edit user details:
setup() {
const store = vuexStore;
const adminId = router.currentRoute.params.adminId;
/** Edit **/
function editUser(formData) {
formData.adminId = adminId;
editAdminAccount(formData).then(response => {
if (response) {
redirectUserTo(ROUTE_NAMES_ADMIN.ADMIN_ACCOUNTS);
saveUserChanges(formData);
}
})
}
// Action
function editAdminAccount(data) {
return store.dispatch(UPDATE_ADMIN_ACCOUNT, data);
}
getSelectedAdmin(adminId);
const selectedAdmin = computed(() => store.getters.getSelectedAdmin);
function getSelectedAdmin(adminId) {
return store.dispatch(GET_ADMIN_BY_ID, adminId)
}
return {
editUser,
selectedAdmin,
}
}
Actions:
updateAdminAccount({commit}, payload) {
let formData = new FormData()
formData.append('email', payload.email)
formData.append('name', payload.name)
formData.append('password', payload.password);
return apiHandler.put(`user/admin/${payload.adminId}`, formData, apiHandler.getAuthHeader()).then(response => {
return !!apiHandler.isSuccess(response.status);
}).catch(error => {
commit(SET_API_ERROR, error);
});
},
You should maybe check what the api call is returning with some console.logs to be sure of the data that is sent back.
Nevertheless, do not have to work with formdata, you can send your query items directly :
updateAdminAccount({commit}, payload) {
return apiHandler.put(`user/admin/${payload.adminId}`, payload, apiHandler.getAuthHeader())
.then(response => !!apiHandler.isSuccess(response.status))
.catch(error => commit(SET_API_ERROR, error));
}
You also should edit the user directly after the api call in the action, and not from the template. So that the logic is kept at one place :
updateAdminAccount({commit}, payload) {
return apiHandler.put(`user/admin/${payload.adminId}`, payload, apiHandler.getAuthHeader())
.then(response => {
if (!!apiHandler.isSuccess(response.status)) {
commit('UPDATE_ADMIN', payload) // payload or response.data depending if api is returning edited object
}
return !!apiHandler.isSuccess(response.status)
})
.catch(error => commit(SET_API_ERROR, error));
}
I joined the site a few days ago.
I'm new here.
I have a problem that I can not solve. I built a function in Nodejs, every time I run the function I want to get information from the server.
On the client side I have this function, which I run, and then save the data, here no problem.
export const getRealtimeConversations = (user) => (dispatch) => {
axios.post('/realtimeConversations', user)
.then((res) => {
dispatch({
type: userConstants.GET_REALTIME_MESSAGES,
payload: res.data
});
})
.catch((err) => console.log(err))
}
I have a series of axios, when I use this line, I run a server-side function.
app.post('/realtimeConversations', FBAuth, getRealtimeConversations);
This is the function on the server side, I have a collection, which I want to access according to details I send from the client. After I have done the calculations I want, I want to return the end result.
exports.getRealtimeConversations = (req, res) => {
db.collection('conversations')
.where('user_uid_1', 'in', [req.body.uid_1, req.body.uid_2])
.orderBy('createdAt', 'asc')
.onSnapshot((querySnapshot) => {
const conversations = [];
querySnapshot.forEach(doc => {
if (
(doc.data().user_uid_1 == req.body.uid_1 && doc.data().user_uid_2 == req.body.uid_2)
||
(doc.data().user_uid_1 == req.body.uid_2 && doc.data().user_uid_2 == req.body.uid_1)
) {
conversations.push(doc.data())
}
});
console.log(conversations);
return res.json(conversations);
})
}
I do not know why but I get that I have a 404 error, I am completely new to it, I think I have a logical error in the server side function, but I'm not sure what I'm doing wrong.
I am trying to load a notification token (notificationToken) that I've stored within Firebase to a React Native component.
Once the notificationToken is loaded to my redux state, I want to check for my device permissions to see if the notificationToken has expired within the function getExistingPermission() that I run in the componentDidMount().
If the token has expired, then I'll replace the token within Firebase with the new token. If it's the same, then nothing happens (which is intended functionality).
When I'm running my function getExistingPermission() to check if the token is up-to-date the Firebase listener that pulls the notificationToken does not load in time, and so it's always doing a write to the Firebase database with a 'new' token.
I'm pretty sure using async/await would solve for this, but have not been able to get it to work. Any idea how I can ensure that the notificationToken loads from firebase to my redux state first before I run any functions within my componentDidMount() function? Code below - thank you!
src/screens/Dashboard.js
Should I use a .then() or async/await operator to ensure the notificationToken loads prior to running it through the getExistingPermission() function?
import {
getExistingPermission
} from '../components/Notifications/NotificationFunctions';
componentDidMount = async () => {
// Listener that loads the user, reminders, contacts, and notification data
this.unsubscribeCurrentUserListener = currentUserListener((snapshot) => {
try {
this.props.watchUserData();
} catch (e) {
this.setState({ error: e, });
}
});
if (
!getExistingPermission(
this.props.notificationToken, //this doesn't load in time
this.props.user.uid)
) {
this.setState({ showNotificationsModal: true });
}
};
src/components/Notifications/NotificationFunctions.js
The problem is probably not here
export const getExistingPermission = async (
notificationToken,
uid,
) => {
const { status: existingStatus } = await Permissions.askAsync(
Permissions.NOTIFICATIONS
);
if (existingStatus !== 'granted') {
console.log('status not granted');
return false;
} else {
let token = await Notifications.getExpoPushTokenAsync();
/* compare to the firebase token; if it's the same, do nothing,
if it's different, replace */
if (token === notificationToken) {
console.log('existing token loaded');
return true;
} else {
console.log('token: ' + token);
console.log('notificationToken: ' + notificationToken);
console.log('token is not loading, re-writing token to firebase');
writeNotificationToken(uid, token);
return false;
}
}
};
src/actions/actions.js
// Permissions stuff
watchPermissions = (uid) => (
(dispatch) => {
getPermissions(uid + '/notificationToken', (snapshot) => {
try {
dispatch(loadNotificationToken(Object.values([snapshot.val()])[0]));
}
catch (error) {
dispatch(loadNotificationToken(''));
// I could call a modal here so this can be raised at any point of the flow
}
});
}
);
// User Stuff
export const watchUserData = () => (
(dispatch) => {
currentUserListener((user) => {
if (user !== null) {
console.log('from action creator: ' + user.displayName);
dispatch(loadUser(user));
dispatch(watchReminderData(user.uid)); //listener to pull reminder data
dispatch(watchContactData(user.uid)); //listener to pull contact data
dispatch(watchPermissions(user.uid)); //listener to pull notificationToken
} else {
console.log('from action creator: ' + user);
dispatch(removeUser(user));
dispatch(logOutUser(false));
dispatch(NavigationActions.navigate({ routeName: 'Login' }));
}
});
}
);
export const loadNotificationToken = (notificationToken) => (
{
type: 'LOAD_NOTIFICATION_TOKEN',
notificationToken,
}
);
Tony gave me the answer. Needed to move the permissions check to componentDidUpdate(). For those having a similar issue, the component looks like this:
src/screens/Dashboard.js
componentDidUpdate = (prevProps) => {
if (!prevProps.notificationToken && this.props.notificationToken) {
if (!getExistingPermission(
this.props.notificationToken,
this.props.user.uid
)) {
this.setState({ showNotificationsModal: true });
}
}
};
Take a look at redux subscribers for this: https://redux.js.org/api-reference/store#subscribe . I implement a subscriber to manage a small state machine like STATE1_DO_THIS, STATE2_THEN_DO_THAT and store that state in redux and use it to render your component. Only the subscriber should change those states. That gives you a nice way to handle tricky flows where you want to wait on action1 finishing before doing action2. Does this help?
I have a route in my app that calls the mongoose method findByIdAndRemove. When I test this route in postman, I can successfully delete documents in my database, but when I call this method from my javascript file in the client, I get an error.
I getting a 404 (the response status I dictated if no document can be found). I also get an error in the terminal saying "can't set headers after they are sent." I'm not sure why I'm getting this error. Why is my route working in postman, but not when I call it from the client-side?
How should I get this working?
Here is my route on the server-side:
exports.deleteEmployee = function (req, res, next) {
const id = mongoose.Types.ObjectId(req.body.id);
Employee.findByIdAndRemove(id, (err, employee) => {
if (err) { return next(err); }
// if no employee with the given ID is found throw 400
if (!employee) { res.status(404).json('No employee with that ID'); }
res.status(200).json(employee);
});
};
Here is where I call this route from the client-side:
export const employeeDelete = ({ id }) => {
const props = { id };
return () => {
axios.delete(`${api.API_ROUTE}/employee/delete`, props)
.then(() => {
// push user back to EmployeeList and reset view stack
Actions.employeeList({ type: 'reset' });
})
.catch(err => {
console.log(err);
});
};
};
You're getting "can't set headers after they are sent." error because you're trying to respond with 200 code after having responded with 400 code.
You should surround the response statements with a if/else statement:
if (!employee) { res.status(404).json('No employee with that ID'); }
else{res.status(200).json(employee);}
It turns out the axios delete method does not take a data object, so when I passed the object called props, it never reached the server. I instead passed id as a url parameter like this:
export const employeeDelete = ({ id }) => {
return () => {
axios.delete(`${api.API_ROUTE}/employee/delete/${id}`)
.then(() => {
// push user back to EmployeeList and reset view stack
Actions.employeeList({ type: 'reset' });
})
.catch(err => {
console.log(err);
});
};
};