There is a list of notifications from the backend. Each notification has a delete button. If I click the delete button of any notification, I want that notification to be deleted.
How do I do this?
my service
const remove = (notificationDto) => {
return new Observable((observer) => { //<NotificationDto>
axiosInstance
.delete(SERVICE_PATH + '/remove', notificationDto)
.then((response) => {
observer.next(response.data);
observer.complete();
})
.catch((err) => {
console.log(err);
});
});
};
html
<div className="notificationlist__container only-desktop">
{props.notification.notificationList.map((notification) => {
return (
<div className="notificationlist__time">
{notification.notificationDay}
<div className="delete__button">
<AS.IconButton onClick={() => notificationDataUpdateDeleteClick(notification)}>
<AS.DeleteIcon />
</AS.IconButton>
</div>
</div>
);
})}
</div>
where i call the service
After sending notification as payload, the problem was solved
import { InAppNotificationsService } from 'services/InAppNotificationsService';
import { NotificationContext } from 'contexts/NotificationContext';
const { notificationData, setNotificationData } = useContext(NotificationContext);
const notificationDataUpdateDeleteClick = (notification) => {
InAppNotificationsService.remove({ data: notification }).subscribe({
next: (response) => {
InAppNotificationsService.allNotifications({ nationalId: tckn, externalContactNumber: contactInfo?.externalContactNumber }).subscribe({
next: (response) => {
setNotificationData(response);
},
error: (error) => {
console.log(error);
}
});
},
error: (error) => {
console.log(error);
}
});
};
Related
I am working on a websocket project in react. But when I send a message, the websocket does reload to display new messages. I have to reload my page manually to show the changes.
Here's my use Effect Hook
useEffect(() => {
if (socket.current) {
socket.current.on('msgSent', ({ newMsg }) => {
console.log('MESSAGE SENT', newMsg)
if (newMsg.receiver === openChatId.current) {
setMessages((prev) => [...prev, newMsg])
setChats((prev) => {
const previousChat = prev.find(
(chat) => chat.messagesWith === newMsg.receiver
)
previousChat.lastMessage = newMsg.msg
previousChat.date = newMsg.date
return [...prev]
})
}
})
}
}, [])
When I remove the useEffect dependency (i.e []), It works but it renders the message multiple times on the screen.
Here's the rest of my frontend client code
const openChatId = useRef('')
const auth = useContext(AuthContext)
const queryMessage = new URLSearchParams(search).get('message')
useEffect(() => {
if (!socket.current) {
socket.current = io(process.env.REACT_APP_API)
}
if (socket.current) {
socket.current.emit('join', { userId: auth.user._id })
socket.current.on('connectedUsers', ({ users }) => {
users.length > 0 && setConnectedUsers(users)
})
}
if (chats.length > 0 && !queryMessage) {
history.push(`/messages?message=${chats[0].messagesWith}`, undefined, {
shallow: true,
})
}
return () => {
if (socket.current) {
socket.current.emit('logout')
socket.current.off()
}
}
}, [chats])
useEffect(() => {
const getAllChats = async (token) => {
try {
setLoading(true)
const res = await getChats(token)
if (res) {
setChats(res)
setLoading(false)
}
} catch (err) {
console.log(err)
setLoading(false)
}
}
getAllChats(auth.token)
}, [])
useEffect(() => {
const loadMessages = () => {
socket.current.emit('loadMessages', {
userId: auth.user._id,
messagesWith: queryMessage,
})
socket.current.on('messagesLoaded', async ({ chat }) => {
setMessages(chat.messages)
setBannerData({
firstName: chat.messagesWith.firstName,
lastName: chat.messagesWith.lastName,
profilePicUrl: chat.messagesWith.profilePicUrl,
})
openChatId.current = chat.messagesWith._id
})
socket.current.on('noChatFound', async () => {
const { firstName, lastName, profilePicUrl } = await ChatGetUserInfo(
queryMessage,
auth.token
)
setBannerData({ firstName, lastName, profilePicUrl })
setMessages([])
openChatId.current = queryMessage
})
}
if (socket.current) {
loadMessages()
}
}, [queryMessage])
const sendMsg = (msg) => {
if (socket.current) {
socket.current.emit('sendNewMsg', {
userId: auth.user._id,
msgSendToUserId: openChatId.current,
msg,
})
}
}
The backend works very well. U think my problem is with the useEffect
I fixed it. I was missing the [chats] dependency
I was wondering if it's possible to re-render this v-if statement inside my component.
I am enabling/disabling a user account through firebase admin functions. This currently works, however whenever I disable a user I have to refresh the page in order to show updates, I can manually refresh, but wondered if there is a way to do this with reactivity? I've tried to update the array manually (UsersAuth contains all the users from Firebase, with the disabled: true|false boolean).
html
<span v-if="usersAuth[index].disabled === true"> <button type="button" v-on:click="enableUser(user.id, index)" class="btn btn-success">Enable</button></span>
<span v-if="usersAuth[index].disabled === false"><button type="button" v-on:click="disableUser(user.id)" class="btn btn-primary">Disable</button></span>
VueJS Methods
data () {
return {
users: [],
user: null,
usersAuth: null,
selecteduser: null
}
},
created () {
// call all users from the firebase store.
const addMessage = firebase.functions().httpsCallable('listAllUsers')
addMessage()
.then(result => {
this.usersAuth = result.data.users
})
firebase.auth().onAuthStateChanged((user) => {
this.user = user
})
this.users = []
firebase
.firestore()
.collection('roles')
.get()
.then(snap => {
snap.forEach(doc => {
const user = doc.data()
console.log(doc.data())
user.id = doc.id
this.users.push(user)
})
})
// get the users' enabled status
},
disableUser (uid) {
const addMessage = firebase.functions().httpsCallable('disableUser')
const data = { uid: uid }
addMessage(data)
.then((result) => {
if (result === true) {
console.log(this.userAuth)
}
})
.catch(function (error) {
console.log(error)
})
},
enableUser (uid, index) {
const addMessage = firebase.functions().httpsCallable('enableUser')
const data = { uid: uid }
addMessage(data)
.then((result) => {
this.usersAuth[index].disabled = true
})
.catch(function (error) {
console.log(error)
})
},
listAllUsers () {
const addMessage = firebase.functions().httpsCallable('listAllUsers')
addMessage()
.then((result) => {
console.log(result)
})
.catch(function (error) {
console.log(error)
})
}
Firebase function (if you require this)
exports.disableUser = functions.https.onCall(async (data, context) => {
if (!context.auth.token.superadmin) return
try {
listUsers = admin.auth().updateUser(data.uid, {
disabled: true
})
.then(function() {
console.log("Successfully disabled user " + data.uid);
})
return true
} catch (error) {
console.log(error)
}
});
exports.enableUser = functions.https.onCall(async (data, context) => {
if (!context.auth.token.superadmin) return
try {
listUsers = admin.auth().updateUser(data.uid, {
disabled: false
})
.then(function() {
console.log("Successfully disabled user " + data.uid);
})
return true
} catch (error) {
console.log(error)
}
});
exports.listAllUsers = functions.https.onCall((data, context) => {
if (!context.auth.token.superadmin) return
try {
return admin.auth().listUsers()
} catch (error) {
console.log(error)
}
});
In your enableUser method, this.usersAuth[index].disabled = true should be this.usersAuth[index].disabled = false, so that you're enabling the user rather than disabling them.
You can read The Vue Instance and Reactivity in Depth for more information about how reacitivty works with Vue.
When a Vue instance is created, it adds all the properties found in
its data object to Vue’s reactivity system. When the values of those
properties change, the view will “react”, updating to match the new
values.
On a side note, if disabled is either true or false, you can simplify your code to:
<span v-if="usersAuth[index].disabled">
and <span v-else>
I have action that always returns Promise.reject:
module.exports = { create: createActionAsync('CREATE_USER', () => {
return Promise.reject({
response: {
type: 'error',
message: 'It will be implemented soon',
},
});
})}
But in component catch block doesn't work:
onAddUser(data) {
const { userActions: { create } = {} } = this.props;
create(data)
.then(() => {})
.catch(err => console.error(err)) // not working
I am getting the comment to delete just fine, but for some reason the callback is not being invoked. I think it could be do to how I pass multiple arguments to the function maybe, but I am not sure.
I will post the code below to help out in this problem.
Show Page:
renderCommentsButtons(comment) {
const { post, user, auth } = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id) {
return (
<div>
<button
onClick={() => this.deleteComment(comment)}
className="btn btn-xs btn-danger">
Delete
</button>
<Link
to={`/posts/${post._id}/comments/${comment._id}/edit`}
className="btn btn-xs btn-warning">
Edit
</Link>
</div>
)
}
}
}
renderComments() {
const { post } = this.props;
return post.comments.map((comment) => {
return (
<li className="list-group-item" key={comment._id}>
<div>
{comment.text} : {comment.author.email}
</div>
{this.renderCommentsButtons(comment)}
</li>
);
});
}
deleteComment(comment) {
const {id} = this.props.match.params;
const {user, post, auth} = this.props;
if(!user) {
return (<div></div>);
}
if(auth) {
if(user._id === comment.author.id){
console.log('comment_id:', comment._id, 'post_id:', post._id);
this.props.deleteComments(post._id, comment._id, () => {
this.props.history.push(`/posts/${post._id}`);
});
}
}
}
Action:
export function deleteComments(post_id, comment_id, cb) {
return function(dispatch) {
console.log('comment_id:', comment_id, 'post_id:', post_id);
axios.delete(`${ROOT_URL}/${post_id}/comments/${comment_id}`)
.then(() => {
dispatch({
type: DELETE_COMMENTS,
payload: comment_id
});
})
.then(() => cb())
.catch((error) => {
console.log(error);
});
}
}
Backend:
exports.deleteComment = function(req, res, next) {
const query = {_id: req.params.comment_id};
Comments.remove(query, function(err, comments) {
if(err) {
return next(err);
} else {
res.json(comments);
}
});
}
.then(() => { dispatch(/* action */) } ) doesn't return any promise, that's why .then(() => cb()) is not executing.
You can try to call callback just after dispatching action.
axios.delete(`${ROOT_URL}/${post_id}/comments/${comment_id}`)
.then(() => {
dispatch({ /* action */})
cb();
})
.catch((error) => {
console.log(error);
});
I use email and password for login at first login and I have a token with getToken() function, after I add localStoreage with AsyncStoreage.setItem("ACCESS_TOKEN",token). I want to refresh to app signup with token and I use signInWithCustomToken(token) but I have an error. its 'auth/invalid-custom-token' (The token you provided is not valid.). I can't login.
DataStore.js
onLogin: function (Data) {
ApiRequest.login(Data)
.then((authData) => {
authData.getToken().then((token)=>{
AccessToken.set(token)
.then(() => Actions.login.completed(authData));
})
.catch((err) => Actions.login.failed(err))
})
.catch((err) => Actions.login.failed(err))
}
ApiRequest.Js
login(data) {
// first.login data = (email.password) && after.login data=(token)
return new Promise((next, error) => {
if (data && data.email && data.password) {
this.firebase.auth().signInWithEmailAndPassword(data.email,data.password)
.then((uData) => {;
next(uData)
})
.catch((err)=> error(err));
} else {
console.log("TOKEN:");
console.log(data);
this.firebase.auth().signInWithCustomToken(data)
.then((authData)=>next(authData))
.catch((err)=>{console.log("Error #232",err)})
}
});
}
AccessToken.Js
get(){
return new Promise((next,error) => {
if(this._accessToken) {
console.log("LastToken");
return next(this._accessToken);
}
AsyncStorage.getItem("ACCESS_TOKEN")
.then((token)=>{
if(token){
next(JSON.parse(token));
}else{
error()
}
})
.catch((err)=>error(err));
});
}
set(token){
this._accessToken=token;
return AsyncStorage.setItem("ACCESS_TOKEN",JSON.stringify(token));
}
Authenticate Listener
actions.auth.listen(function () {
AccessToken.get()
.then((token) => actions.login(token))
.catch((err) => actions.logout());
})
Token
eyJhb...Ckz95w