I'm trying to create a React app that:
- sends data (json message) from backend to frontend using socket.io
- if a json message with same is sent, update the existing list
This is how i'm implementing it right now but i'm not sure if this is a good design methodology or if there's a better way to achieve what I want to do.
function App(){
const [database, setDatabase] = useState([])
useEffect(() => {
socket.on('incoming_data', (data) => {
setDatabase((currentList) => {
if (currentList.length > 0){ //only check for update/delete if more than 1 item present
let exists = !!currentList.find((item) => item.ID === data.ID)
if (exists){ //if new item exists in database list
if (data.deleteFlag === true){ // incoming data will have a json field declaring whether to delete or not
//deleting item
var item = currentList.find(itm => itm.ID === data.ID)
let ind = currentList.indexOf(item)
return (currentList.splice(ind,1))
}
else{ // else if delete flag is not true... update fields
var item = currentList.find(itm => itm.ID === data.ID)
let ind = currentList.indexOf(item)
if (item.dataField !== data.dataField){
currentList[ind].dataField = data.dataField
}
return (currentList)
}
}
//if incoming data doesnt exist in list, add to it
else{ return([...currentList, data]) }
}
}
// if there are 0 items in list, add to list
else { return ([...currentList, data]) }
})
}, [socket])
return(/*using map to display list in front end*/)
}
Right now, this code works in the following ways:
- Checks if there are 0 items in 'database', if so, it adds items to it.
What it's not doing:
- updating items in database
- deleting items properly. Sometimes it deletes items, other times it does nothing.
Any help would be great!
CodePudding user response:
There's a few features in modern JavaScript that I think might help you simplify things here.
For example, I see you're using Array.find
to see if something exists. There's a function that does just that, Array.some
.
If you need items to be unique, you could try storing them as an object keyed by the ID of the items. React's state can work quite well for this, and finding things in the object is as simple as database[data.ID]
, with the caveat that you need to make a copy of the item each time like const newData = { ...data }
so that you can work with code that expects immutability.
If you're feeling like really diving in, methods like Array.reduce
might help you really simplify the code here with some refactoring effort.
Hope some of this helps :)
Oh, there's also a special kind of object called a Set
(instead of Object
or Array
) that might suit your needs, but again make sure to follow immutability rules.
CodePudding user response:
Use higher-order functions to simplify code like filter, findIndex, etc.
use findIndex method to check items exist and use the same index to update currentList.
use the filter function to delete items from the list.
function App() {
const [database, setDatabase] = useState([])
useEffect(() => {
socket.on('incoming_data', (data) => {
setDatabase((currentList) => {
if (currentList.length > 0) { //only check for update/delete if more than 1 item present
// Use same index to find item
let itemIndex = currentList.findIndex((item) => item.ID === data.ID)
if (itemIndex !== -1) { //if new item exists in database list
if (data.deleteFlag === true) { // incoming data will have a json field declaring whether to delete or not
// use filter for delete
return currentList.filter((item) => item.ID !== data.ID);
}
else {
let item = currentList[itemIndex]
const newItem = { ...item, dataField: data.dataField }
if (item.dataField !== newItem.dataField) {
currentList[itemIndex] = newItem;
return [...currentList]; // Set new value for updates
}
return (currentList)
}
}
//if incoming data doesn't exist in list, add to it
else { return ([...currentList, data]) }
}
// if there are 0 items in list, add to list
else { return ([...currentList, data]) }
});
});
}, [socket])
return (/*using map to display list in front end*/)
}