How to check if the array has received a new value? - javascript

I'm trying to create a custom notification counter, which shows the number of notifications that are unread.
I receive the notification content from the backend as an array.
My idea is to get the first value, check if the previous length is different from the current length, and add to this counter +1(or more).
useEffect(() => {
axios
.get(USER_API)
.then((response) => {
setNotificationList(response.data.data);
})
.catch((error) => console.log('error from getNotifications', error));
});
How can I make it work?

As right way could be that you place a key isRead in the backend.
and setThis key to true via api when user click on the notification.
and count the length of those items who has isRead false and set it to counter.
this way you will not be dependent on local state and this will work even if app is killed or uninstalled.
useEffect(() => {
axios
.get(USER_API)
.then((response) => {
const data = response.data?.data;
const unReadItems = data.filter((item)=> !item.isRead)
setUnReadCount(unReadItems.length)
setNotificationList(data);
})
.catch((error) => console.log('error from getNotifications', error));
});

use the callback function in set state
setNotificationList((prev) => {
if(prev?.length === response.data.data.length) return prev
return response.data.data
} );

Related

Javascript issue storing user id when updating Strapi

For a research study, I am trying to record user's interactions with a web interface. I setup a back end with Strapi to store that data. Connection and setting up of a new participant ID is not a problem, but when I try to update the data I get an interesting behavior that is unfamiliar to me.
Basically, it seems that I am setting the participants ID but when accessing it, my logs show that I have a duplicate with no data stored. Below the logs I am getting while debugging:
//Initialising study. connectStrapi.js?t=1668867760343:11
//No participant ID existing. Creating.. connectStrapi.js?t=1668867760343:15
//Confirming, Participant ID: 121 interactionLogger.js?t=1668867760343:199
//On Event: participant id is: 121. interactionLogger.js?t=1668867760343:81
//On Event: participant id is: undefined interactionLogger.js:81
The connectStrapi.js sets up the study and participant data. When no id is present at the start, I am creating new data. The interactionLogger.js is responsible to log the data and update Strapi when something happens.
I am not completely new to JavaScript, but I go to admit, that I have no idea what the different identifiers mean. I am only updating once, but I the same line twice - once for interactionLogger.js?t=1668867760343:81 and a second time for interactionLogger.js:81. I am not exactly sure, what the .js?t=1668867760343 means and how I can ensure passing the right value at the right time.
Currently, I when I am updating the data, the undefined value is being passed resulting in no data being updated. I am thinking, I am missing something basic here but can't figure it out.. In case it matters, I have implemented the JavaScript files as type=modules and import functions accordingly.
InitialiseStudy function from connectStrapi.js:
import * as interactionLogger from './interactionLogger.js/'
//...
export const initialiseStudy = async (participantData, id) => {
console.log("Initialising study.")
if(id === undefined) {
await axios.post(apiUrl, participantData)
.then( response =>{
console.log('No participant ID existing. Creating..')
//setupParticipant(response.data.data);
interactionLogger.setParticipantID(response.data.data.id)
})
.catch( error => {
if (error.response){
console.log('error:', error.response)
}
else if (error.request){
console.log('error:', error.request)
}
else if (error.message){
console.log('error:', error.message)
}
else {
console.log('error:', error)
}
})
} else {
axios.put(apiUrl+ id, participantData)
.then(response => {
console.log('response.data:', response.data)
})
.catch( error => {
console.log('error:', error)
})
}
}
My updateData function from connectStrapi.js:
export const updateData = (data, id) => {
if (id === undefined) {
alert("No Participant ID")
} else {
axios.put(apiUrl + '/' + id, data)
.then( response => {
console.log('response.data:', response.data)
} )
.catch( error => {
console.err('error:', error)
})
}
}
The setter from interactionLogger.js is a normal setter:
let participantID
//...
export const setParticipantID = (id) => {
participantID = id
}
The logData function uses updateData, which is imported before it based on events in interactionLogger.js:
import * as connectStrapi from './connectStrapi.js'
//...
const logData = (data) => {
connectStrapi.updateData(data, participantID) //<- This is a local variable initialized as undefined but updated using the setParticipantID in connectStrapi.js
}
Thanks in advance!

React Native Firebase adding and getting data

wondering if anyone can assist me in this matter. I'm following the documentation for https://rnfirebase.io/firestore/usage. it does not work for my use case for some reason.
I just need to set the data, which it works and then read it back so i can push it onto my state and i'll render it.
I just can't read the data back properly. This addItemFunction is trigger when when user click on a button to add.
const addItemFunction = async (numb,exercise) =>{
firestore().collection(userEmail).get().then((snap) =>{
if(!snap.empty){
var finalID = uuid.v4();
firestore().collection(userEmail).doc(final).update({
[finalID]:{
exe:[exercise],
num:[numb],
}
}).then(() =>{
//RETURN SNAPSHOT NOT WORKING
console.log('user_added');
firestore().collection(userEmail).doc(final).onSnapshot(documentSnapshot =>{
console.log("here" + documentSnapshot.data());
});
}
Thanks for your time.
If you are using react with hooks I would suggest you put the onSnapshot listener in a useEffect hook:
useEffect(() => {
const unsubscribe = firestore
.collection(collectionName)
.doc(docId)
.onSnapshot(
(documentSnapshot) => {
const document = documentSnapshot.data();
console.log(document)
},
(error: Error) => {
throw error;
}
);
return () => unsubscribe();
}, [ docId, collectionName]);
this approach will separate concerns and the snapshots will run every time there is a change on the document, then where I put the console.log you could set the document to state.
Another approach will be to use get() instead of onSnapshot like:
const addItemFunction = async (numb,exercise) =>{
firestore().collection(userEmail).get().then((snap) =>{
if(!snap.empty){
var finalID = uuid.v4();
firestore().collection(userEmail).doc(final).update({
[finalID]:{
exe:[exercise],
num:[numb],
}
}).then(() =>{
console.log('user_added');
firestore().collection(userEmail).doc(final).get().then(() => {
console.log("here" + documentSnapshot.data());
})
}
}
}
this approach will not subscribe to changes and it will return the new updated document every time you call the addItemFunction

How to use UseEffect every time get user and axios?

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

How to retain the order of items (from server) for a key-index object after normalizing?

I am working on a react asp.net application. From the server, I return a list of items, ordered by date. Then, I normalize it using normalizr:
axios.get(url, { params: { userId, submissionId } })
.then(response => {
const notifications = new schema.Entity('notifications');
const normalizedData = normalize(response.data, [notifications]);
dispatch(
fetchNotificationsSuccess(normalizedData.entities.notifications)
);
})
.catch(error => { notificationDataOperationFailure(error) });
When I run this, the items are reordered by their key values starting from 1. I wonder how I can retain the order sent from the server.
You can find the order in the "result" you get, see more info here: https://github.com/paularmstrong/normalizr/issues/9

[TypeError]: Firebase orderByChild not working

I'm trying to query my database such that it retrieves an ordered list based on each child key. I do it as follows (see below), but "TypeError" happens. That is ordered at random when using .on('value', snapshot =>. I can't fix that, do you guys have any ideas to realize?
The Error
TypeError: In this environment the sources for assign MUST be an object. This error is a performance optimization and not spec compliant.
Realtime Database Query
Source Code
export const messagesFetch = (room) => {
return (dispatch) => {
firebase.database().ref(`/rooms/${room.roomId}/messages`)
.once('child_added', snapshot => {
dispatch({ type: 'messages_fetch_success', payload: snapshot.val() });
})
};
};
child_added will create a new snapshot for each message, instead of returning a list of messages in one object.
You might want to look at .once('value') instead of once('child_added').
As you wanted an ordered list I added the query orderByKey() which will return the messages in key order.
export const messagesFetch = (room) => {
return (dispatch) => {
firebase.database().ref(`/rooms/${room.roomId}/messages`)
.orderByKey()
.once('value')
.then(snapshots => {
snapshots.forEach(snapshot => {
dispatch({ type: 'messages_fetch_success', payload: snapshot.val() });
return false;
});
});
};
};
Is a react-native app, right?! If yes add a flag in question.
In firebase 'child_added' fires for each child and ever a new child has add, like sketchthat says. With 'once' you not listen the node, but, because 'child_added' you fires your function for every child. In other words your function return differents values (snapshot) for a same constant.

Categories