AsyncStorage mergeItem - Unrecognised selector - react-native

Hi I'm trying to do a simple get and update using AsyncStorage in react native.
I get the data in componentDidMount() using the following code:
AsyncStorage.getItem('mytrips', (err, result) => {
if(result !== null){
var data = JSON.parse(result);
console.log(result);
this.setState({
email: data.email,
firstname: data.firstname,
lastname: data.lastname,
phone: data.phone,
mobile: data.mobile,
phonecode: data.phonecode,
DOB: moment(data.DOB).format('DD MMM YYYY'),
});
}
});
Following some user input I want to update what's in storage using mergeItem.
AsyncStorage.mergeItem('mytrips', JSON.stringify(data));
data is an object of all the changed values.
I get the following error when mergeItem is called.
ExceptionsManager.js:71 Exception '-[__NSArrayI objectForKeyedSubscript:]: unrecognized selector sent to instance 0x600000886400' was thrown while invoking multiMerge on target AsyncLocalStorage with params (
(
(
mytrips,
"[\"Carl\",\"Carl\",\"11111111\",\"111111111\",\"\",\"1900-01-01\",\"carl#test.com\"]"
)
),
3657
)
Any idea what could be causing the selector to be unrecognised? I'm not calling removeItem anywhere in my code.

You are merging an array of items as I can see. You can't merge an already stored JSON item with the array of items. As stated in the react-native docs:
MergeItem: Merges an existing key value with an input value, assuming both values are stringified JSON. Returns a Promise object.
Please try and merge the JSON object with the already saved item to work properly. I hope this solves your problem and if not please let me know :)

Related

[Vue warn]: Invalid prop: type check failed for prop "Items". Expected array, got Promise

I am new to the entire node technology stack and trying to improve myself by taking on a project. At this point I have had moderate success (possibly by chance), but I am currently stuck. My client side is using 'axios, vue, vue-router, vuetify' and a few others. The server side code is 'axios, bluebird, sequelize and sqlite3'.
My issue is as follows, I am trying to populate a 'v-data-table' by making the following function call:
<v-data-table
:headers="task_headers"
:items="getTasks(props.item.upgrade_id)"
hide-actions
item-key="task_id"
>
My function looks as follows:
methods: {
async getTasks (id) {
try {
console.log('JAC in getTask value of id is: ', id)
this.tasks = await TasksService.show(id)
console.log('JAC value of this.tasks is typeof: ', typeof this.tasks)
console.log('JAC value of this.tasks values are: ', Object.values(this.tasks))
console.log('JAC value of this.tasks keys are: ', Object.keys(this.tasks))
return this.tasks.data
} catch (err) {
console.log(err)
}
}
My debug messages produce the following output:
JAC value of this.tasks is typeof: object
JAC value of this.tasks values are:
(6) [Array(9), 200, "OK", {…}, {…}, XMLHttpRequest]0:
JAC value of this.tasks keys are:
(6) ["data", "status", "statusText", "headers", "config", "request"]
this.tasks values Array of 9 is carrying the data returned from the db that I need, but I do not understand how to return the data. I have many other service calls to the backend which are working just fine. v-data-table is expecting an array and I do not understand what I am missing to get this to work.
async getTasks (id) { <- remove async, and return an array
You are expecting in v-data-table an array and with the async property, it will return a promise therefore you got that error.
If you dont want to remove that, you can do something like this.
getTasks(props.item.upgrade_id).then((data) => {
this.tasks = data;
})
<v-data-table
:headers="task_headers"
:items="tasks"<- updated this line and no longer it will return a promisa
hide-actions
item-key="task_id"
>

Pouchdb query() leaving out documents on emit()

For some reason my filter is not working correctly. It was working fine a moment ago and then for some reason it stopped returning all of the templates and only started returning one of them.
Why might it be returning it twice but only giving me one?
I have the following code:
export async function testMe() {
const company_id = await AsyncStorage.getItem('company_id');
const device_db = new PouchDB(company_id, {});
device_db.query(function(doc, emit){
console.log(doc.type, doc._id, doc._rev);
if(doc.type == 'template') {
emit(doc._id, doc);
}
}).then((result) => {
console.log("Returned", result);
})
}
What is unexpectedly happening is this is what gets returned:
template template_1 18-5918af4c5370d9755d0bb8b6dcb21ea1
template template_2 19-8191dec49dfa8c1a2f03d752a193f09e
template template_3 39-74f3b82ce4a38a501810b5ff31efc593
undefined "dpbcab6843-2cdf-4d4c-87ae-286dcddaac22" "2-8f03f3127771dadd3c8f7beb3e827982"
undefined "dpdc6f6cd0-6c6d-4974-a166-b848a0217af4" "2-0eec1a8d925641aa8bf30e058e6515e7"
undefined "dpe1573a70-a281-4e15-a997-82d8bf8fabfa" "2-d3bbcb81344f61cc94459610695c6670"
template template_3 39-74f3b82ce4a38a501810b5ff31efc593
You can ignore the undefined, but what I am trying to show is look at what gets returned twice:
template template_3 39-74f3b82ce4a38a501810b5ff31efc593
In the Returned console.log(), this is the only thing that gets returned (the last template_3 piece of data, totally ignoring the other templates even though they are both type template):
{"total_rows":6,"offset":0,"rows":[{"key":"template_3","id":"template_3","value":{..}}]}
Edit
It's getting even weirder. I just opened template_2 and did a save (in Cloudant) and synced it with my device to update the _rev and now I get:
template template_1 18-5918af4c5370d9755d0bb8b6dcb21ea1
template template_2 20-c549fe868735ef0099b80f6668af611c
template template_3 39-74f3b82ce4a38a501810b5ff31efc593
undefined "dpbcab6843-2cdf-4d4c-87ae-286dcddaac22" "2-8f03f3127771dadd3c8f7beb3e827982"
undefined "dpdc6f6cd0-6c6d-4974-a166-b848a0217af4" "2-0eec1a8d925641aa8bf30e058e6515e7"
undefined "dpe1573a70-a281-4e15-a997-82d8bf8fabfa" "2-d3bbcb81344f61cc94459610695c6670"
template template_3 39-74f3b82ce4a38a501810b5ff31efc593
template template_2 20-c549fe868735ef0099b80f6668af611c
Which returns (leaving out template_3):
{"total_rows":6,"offset":0,"rows":[{"key":"template_2","id":"template_2","value":{..}}]}
Edit 2
I added:
.catch((err) => {
console.log(err);
})
And get this: {"status":409,"name":"conflict","message":"Document update conflict","error":true}
However, I do the following an all _conflict arrays are empty:
device_db.allDocs({conflicts: true})
.then((data) => {
for (let d of data.rows) {
console.log(d.doc._conflicts);
}
});
I believe temporary queries like this should have a key, otherwise the query would not know what documents you want to select. The example from the PouchDb docs is
db.query(function (doc, emit) {
emit(doc.name);
}, {key: 'foo'}).then(function (result) {
// found docs with name === 'foo'
}).catch(function (err) {
// handle any errors
});
so that documents with a "name" field equal to "foo" are returned by the query. In your query the key appears to be undefined. This might explain the odd results you are getting?

Component method response object data binding

I am starting to lose my mind in debugging an application that I inherited from a fellow developer who is absent.
I have narrowed down the problem to the following place in code (php files are checked, Vue instances are initialised, there are no syntax errors).
This is my the component that gets initialised:
var RadniStol = Vue.component('radnistol', {
template: '#template-RadniStol',
data() {
return {
tableData: [],
requestData: {
sort: "ID",
order: "DESC"
}
}
},
methods: {
reloadTable: function (event) {
data = this.requestData;
this.$http.post('php/get/radni_stol.php', data).then(response => {
console.log(response.data.bodyText);
this.tableData = response.data.records;
});
},
.
.
.
The PHP file that gets called with the POST method is working correctly, querying the database and echoing the response in a JSON format.
The thing that is making me pull out my hair is the following: the console.log(response.data) outputs the following into the console:
{"records":[{"DODAN_NA_RADNI_STOL":"1","..."}]}
It is an JSON object that I expected to have but when trying to assign it to the data of the component with:
this.tableData = response.data;
or any other way… response.data.records returns ‘undefined’ in the console. I have tryed with JSON.parse() but no success.
When logging types to console:
response variable is a response object with a status 200 and body and bodyText containing the data from the database.
response.data is a string type containing the string JSON with the data from the database.
When trying to use JSON.parse(response.data) or JSON.parse() on anything in the callback of the POST method I get the following error in the console:
RadniStol.js?version=0.1.1:17 Uncaught (in promise) SyntaxError: Unexpected token in JSON at position 0
at JSON.parse (<anonymous>)
at VueComponent.$http.post.then.response (RadniStol.js?version=0.1.1:17)
at <anonymous>
I am really starting to lose my mind over this issue, please help!
Thank you
If response.data is string, with JSON inside, then to access the records field, you should decode it like this:
JSON.parse(response.data).records
Not sure this has something to do with PHP or Vue.js, it is just plain javascript issue.
If it not decodes, than problem is definitely in response.data. For example
{"records":[{"DODAN_NA_RADNI_STOL":"1","..."}]}
is not a valid JSON, because key "..." needs to have some value.
But it seems to me that response.data is already parsed.
What I suggest you to do, is to write handler of the response as separate function, make response object that mimics actual response object by hand, and then test it separately from request. So you could show us request object and function that works with it.
I had the same error and fixed it.
Result will be response.body not response.data.
Here is my code:
getS: function(page) {
this.$http.get('vue-manager?page=' + page).then((response) => {
var data = JSON.parse(response.body);
this.student = data.data.data;
this.pagination = data.pagination;
});
},

how to push values in array and pass these values to Select tag

I want to push values in array and pass these values as options of select tag. I did following,
used plugin
import DropDown, {
Select,
Option,
OptionList,
} from 'react-native-selectme';
assigned state as
this.state = {company:[]};
pushing in this array as
for(let i in data.companyRecord)
company.push(data.companyRecord[i].companyname);
and assigning to select tag as
<Select
width={250}
ref="SELECT1"
optionListRef={this._getOptionList.bind(this)}
defaultValue="Select a Company ..."
onSelect={this._company.bind(this)} asyncOptions={this.state.company}>
</Select>
But it is not working. It is showing that
undefined is not an object('evaluating children.length').
Please help me solving this issue.
You can't edit the state like that.
const tempNames = [];
for(let i in data.companyRecord)
tempNames.push(data.companyRecord[i].companyname);
this.setState({ company: tempNames });
Now your state will have the correct values.
But there might still be some problem, because your error might suggest that this.state.company is undefined, however you correctly assigned this.state.company to an empty array before.
This could be due to this.state is undefined. Are you defining your selector in a own created function? And not in your class own render method? In that case you need to bind this to your method.
renderSelector() {
return (<Select
width={250}
ref="SELECT1"
optionListRef={this._getOptionList.bind(this)}
defaultValue="Select a Company ..."
onSelect={this._company.bind(this)} asyncOptions={this.state.company}>
</Select>);
}
In your constructor you need to bind "this" to that method. Like this:
this.renderSelector = this.renderSelector.bind(this);

vue js returned value gives undefined error

i want to check the returned value of $http.get() but i get undefined value. Here is my vue js code:
var vm = new Vue({
el: '#permissionMgt',
data: {
permissionID: []
},
methods:{
fetchPermissionDetail: function (id) {
this.$http.get('../api/getComplaintPermission/' + id, function (data) {
this.permissionID = data.permissionID; //permissionID is a data field of the database
alert(this.permissionID); //*****this alert is giving me undefined value
});
},
}
});
Can you tell me thats the problem here?.. btw $http.get() is properly fetching all the data.
You need to check what type is the data returned from the server. If #Raj's solution didn't resolve your issue then probably permissionID is not present in the data that is returned.
Do a colsole.log(data) and check whether data is an object or an array of objects.
Cheers!
Its a common js error. Make the following changes and it will work.
fetchPermissionDetail: function (id) {
var self = this; //add this line
this.$http.get('../api/getComplaintPermission/' + id, function (data) {
self.permissionID = data.permissionID; //replace "this" with "self"
});
},
}
the reason is this points to window inside the anonymous function function()
This is a well known js problem. If you are using es2015 you can use arrow syntax (() => { /*code*/ }) syntax which sets this correctly