Prevstate in reactJs - react-native

This might be a silly question, but how do I get data if I saved the state using prevState.
I am trying to retrieve data from database and send that data through navigation.
const [dataFromDatabase, setDataFromDatabase] = useState('');
const retrieveFromDatabase = () => {
db.transaction(
tx => {
tx.executeSql("SELECT * FROM PreLoveeedTable",
[],
(_, { rows }) => {
console.log("ROWS RETRIEVED");
// clear data currently stored
setDataFromDatabase('');
let entries = rows._array;
entries.forEach((entry) => {
setDataFromDatabase(prev => prev + `${entry.id}, ${entry.image}, ${entry.title}, ${entry.price}, ${entry.description}\n
});
},
(_, result) => {
console.log('SELECT failed!');
console.log(result);
}
)
}
);
}
{dataFromDatabase} will give me the whole entire data in the database.
But wanted to have each entry in the Database. For example entry for title.
I have been stuck on this for a while now and would be appreciated it if i can get a hint.

Related

Duplicate items in list after an API update

I'm learning vuejs and I'm doing a weather app, the goal is to rank cities with an index (humidex). I fetch weather information by API (axios) in order to collect data from several cities. I want to auto update data every x minutes, problem : some of my results are duplicated (the new data don't replace the old one).
I tried to set an unique key (based on latitude and longitude) for each item, it works for several results but not for all.
data () {
return {
items:[],
show: false,
cities: cities,
newCity:''
}
},
components: {
Item
},
computed: {
sortHumidex() {
return this.items.slice().sort((a,b) => {
return this.getHumidex(b) - this.getHumidex(a) || b.current.temp_c - a.current.temp_c
})
}
},
methods: {
addCity() {
if (this.newCity.trim().length == 0) {
return
}
this.cities.push(this.newCity)
this.newCity = ''
},
getHumidex: (el) => {
const e = 6.112 * Math.pow(10,(7.5*el.current.temp_c/(237.7+el.current.temp_c)))
*(el.current.humidity/100)
return Math.round(el.current.temp_c + 5/9 * (e-10))
},
indexGeo: (e) => {
const lat = Math.round(Math.abs(e.location.lat))
const lon = Math.round(Math.abs(e.location.lon))
return lat.toString() + lon.toString()
},
getApi: function () {
const promises = [];
this.cities.forEach(function(element){
const myUrl = apiUrl+element;
promises.push(axios.get(myUrl))
});
let self = this;
axios
.all(promises)
.then(axios.spread((...responses) => {
responses.forEach(res => self.items.push(res.data))
}))
.catch(error => console.log(error));
}
},
created() {
this.getApi()
this.show = true
}
}
The render when I update API :
By pushing to the existing array of items, you have to deal with the possibility of duplicates. This can be eliminated simply by replacing items every time the API call is made.
Replace:
responses.forEach(res => self.items.push(res.data))
with:
self.items = responses.map(res => res.data)

Why can I add, but not remove an element from a set

I’m trying to update the notification count in my database.
I’m doing this by creating a set, which I add a UID to when I want to add to the notification count and removes a UID from the set when I want to subtract from the notification count.
I then take the size of the set and update the notification count.
the updateNotificationCount function is triggered by a lower order component.
However I can only get the database to update when isNewMatch is true. Why won’t it update the database when isNewMatch is false?
state = {notificationSet: new Set()}
updateNotificationCount = (uid, isNewMatch) => {
if (isNewMatch) {
this.setState(({ notificationSet }) => ({
notificationSet: new Set(notificationSet).add(uid)
}));
}
else {
this.setState(({ notificationSet }) => {
const newNotificationSet = new Set(notificationSet);
newNotificationSet.delete(uid);
return {
notificationSet: newNotificationSet
};
});
};
}
You don't need to do new Set() every time because you already initialize the state with new Set() so now you just do as follow:
state = {notificationSet: new Set()}
updateNotificationCount = (uid, isNewMatch) => {
let notificationSet;
if (isNewMatch) {
notificationSet=this.state.notificationSet;
notificationSet.add(uid);
this.setState({
notificationSet: notificationSet
});
} else {
notificationSet=this.state.notificationSet;
notificationSet.delete(uid);
this.setState({
notificationSet : notificationSet
});
};
}

Is it good practice to use for loops to sort out data in the same function where it's fetched in Vue?

I am using fetch to get some data from an API, I convert this to JSON and want to sort it into different categories. For example tickets (which is what I'm retrieving) with the status active should be in a different array than the ones with status waiting on customer. I want to use a for loop to sort through the results. Should I do this in the same function they're fetched in?
Did a bit of googling but couldn't find a post on this.
methods: {
fetchTickets() {
fetch('/api')
.then(res => res.json())
.then(resJson => {
arrayLength = resJson.length
for(var i = 0; i < arrayLength; i++) {
if(resJson[i]['status'] === 'active') {
//do something
}
else if(resJson[i]['status'] === 'waiting on customer') {
// do something else
}
else {
// do a dance
}
}
});
},
}
So, is it okay to do the above or is it very sensitive to errors/is there a more convenient alternative?
There is a more convient alternative.
You should create two API calls.
1.) /api/activeUsers
2.) /api/waitingCustomers
Then for each API call, you can use the .filter API and return the appropiate array
fetchActiveTickets() {
fetch('/api')
.then(res => res.json())
.then(resJson => {
return resJson.filter(item => {
return item.status ==='active'
})
//do the same for waiting... i.e. resJson(item => {
//return item.status ==='waiting'
//})
}
});
},
I would recommend using .filter() rather than looping over the array to split the source into the pieces you want.
data: {
activeTickets: [],
waitingTickets: []
}
methods: {
fetchTickets() {
fetch('/api')
.then(res => res.json())
.then(resJson => {
this.activeTickets = resJson.filter(function(ticket) { return ticket.status === 'active' });
this.waitingTickets= resJson.filter(function(ticket) { return ticket.status === 'waiting on customer' });
// do things with your filters arrays...
});
},
}
Try
methods: {
async fetchTickets() {
let res = await (await fetch('/api')).json();
let active = res.filter(x=> x['status']=='active');
let waiting = res.filter(x=> x['status']=='waiting on customer');
// ... do something
},
}

Array being populated by itself

I'm having am issue with an array that seems to be getting populated with my mongoose code by itself. It's making it impossible to populate the array with modified values.
Here's the code:
router.get('/in-progress', function(req, res) {
console.log('exporting');
var dataset = [];
Intake.find({}, function(err, intakes) {
if(err){
console.log(err);
} else {
/*intakes.forEach(function(intake) {
dataset.push(
{
//requestName: intake.requestName,
requestName: 'Request Name',
status: intake.phase
}
)
});*/
return dataset;
}
}).then((dataset) => {
console.log(dataset);
const report = excel.buildExport(
[
{
heading: inProgressHeading,
specification: inProgressSpec,
data: dataset
}
]
);
res.attachment('requests-in-progress.xlsx');
return res.send(report);
});
});
As you can see, the logic to push data to "dataset" is commented out, but the console log is logging every Intake that I have in the MongoDB database. Does anyone know what I am doing wrong so that I can push my own values into "dataset"?

Filtering normalized data structure

Forgive me, I'm new to normalizr+redux. I've managed to normalize my data and create a reducer and end up with :
state = {
installations:{
"1":{...},
"2":{...}
}
}
I would then like to filter this data for use in a UI component into two separate categories (in this case where the installation.operator is equal to the current user). I've managed an implementation that works however it seems exhaustive:
const mapStateToProps = (state, ownProps) => {
console.log("mapStateToProps", state.installations);
let assignedInstallations = Object.keys(state.installations)
.filter(i => {
return state.installations[i].operator == state.login;
})
.map(i => {
return state.installations[i];
});
let unassignedInstallations = Object.keys(state.installations)
.filter(i => {
return state.installations[i].operator != state.login;
})
.map(i => {
return state.installations[i];
});
return {
assignedInstallations,
unassignedInstallations,
loginUserId: state.login
};
};
I'm also new to ES6 and am not across all the new syntax shortcuts etc so I suspect there are much better ways to do this.
Is there a more succinct approach with a similar outcome?
you can do this with only one reduce():
const mapStateToProps = (state, ownProps) => {
console.log("mapStateToProps", state.installations);
let {assignedInstallations,
unassignedInstallations } = Object.keys(state.installations)
.reduce(function(acc, cur, i){
if(state.installations[i].operator == state.login){
acc.assignedInstallations.push(state.installations[i]);
}else{
acc.unassignedInstallations .push(state.installations[i]);
}
return acc
}, {assignedInstallations: [], unassignedInstallations: [] })
return {
assignedInstallations,
unassignedInstallations,
loginUserId: state.login
};
};
lodash (An utility library) have a notion of collection (Here is an example https://lodash.com/docs/4.17.4#filter for filter function). It takes as input Object or Array and returns an Array. It seems to fit to your needs. Here is the refactored code:
import {
filter,
} from 'lodash'
const mapStateToProps = (state, ownProps) => {
let assignedInstallations = filter(state.installations, installation => installation.operator == state.login);
let unassignedInstallations = filter(state.installations, installation => installation.operator != state.login);
return {
assignedInstallations,
unassignedInstallations,
loginUserId: state.login
};
};