I am just creating a function to update existing value from my state with immutable js even though the code look fine to me it throws invalid KeyPath Err
const initialState = fromJS({
all:[],
tags:[],
isPaginationData:true,
isContactFetchingPagination:false
});
.....
const findAndUpdateContact = (state,action) => {
let {payload} = action;
let findIndex = state.get('all').findIndex(i => i._id === payload._id);
if(findIndex !== -1){
console.log(typeof findIndex,findIndex);// Returns number , 0
console.log(state.deleteIn(['all',findIndex]),"New State"); // not deleting throws an error
return state
}else {
return state
}
};
....
You can use setIn to update your data once you have found the index you want to update.
I would first find the index (as you did):
let findIndex = state.get('all').findIndex(i => i.get('_id') === payload._id);
and then update the state with:
return state.setIn(['all', findIndex], 'new state');
Related
Error Message: Function WriteBatch.set() called with invalid data. Data must be an object, but it was: www.google.com
I have a button that onclick runs the addQuotes function.
Where am I going wrong?
const addQuotes = async () => {
let test = ['https://www.google.com/', 'https://www.google.com/about',]
const obj1 = Object.assign({}, test);
const batch = writeBatch(db);
Object.keys(obj1).forEach(key => {
var docRef = db.collection("col").doc(); //automatically generate unique id
batch.set(docRef, obj1[key]);
});
batch.commit().then(function () {
console.log("hello")
});
}
As the error says, the data param should be an object (second argument to the batch.set method)
Commented out the firebase methods invocation for running the code
and show you the o/p
// In your case when you do
let test = ['https://www.google.com/', 'https://www.google.com/about', ]
const obj1 = Object.assign({}, test);
console.log(obj1);
// and ignoring the unique id step
Object.keys(obj1).forEach((key, index) => {
// var docRef = db.collection("col").doc(); //automatically generate unique id
console.log(obj1[key]); // here it is just the string value
console.log({[index]: obj1[key]}); // here it is an object
//when you do the bellow line
// batch.set(docRef, obj1[key]); // value of obj1[key] is just string which is not the correct type
// may be you do something as below (key can be as you want it to be)
// batch.set(docRef, {[index]: obj1[key]}); // index is added as key for the object which in now an object and should work
});
I used {[index] : obj1[key]} notation which is computed property in object
Hope it's clear 🙂
If i have this code
ArbFileProvider.js
const fs = require("fs");
class ArbFile {
constructor(arbFile) {
this.arbFile = arbFile;
}
async read() {
const arbFileContents = await fs.promises.readFile(this.arbFile);
this._arbFileObject = JSON.parse(arbFileContents.toString());
console.log(this._arbFileObject);
this._getRessources();
console.log(JSON.stringify(this.ressources));
console.log(JSON.stringify(this.properites));
}
_getRessources() {
const ressourcesKeys = Object.keys(this._arbFileObject).filter(
key => key.match(/^#{1,2}/g) == undefined
);
console.log("ressourcesKeys", ressourcesKeys);
this.ressources = new Map();
ressourcesKeys.forEach(key => {
this.ressources.set(key, {
value: this._arbFileObject[key],
...(this._arbFileObject[
Object.keys(this._arbFileObject).find(val => val == `#${key}`)
] || {})
});
});
console.log("ressources", JSON.stringify(this.ressources));
const propertiesKeys = Object.keys(this._arbFileObject).filter(
key => key.match(/^##/g) != undefined
);
this.properites = new Map();
propertiesKeys.forEach(key => {
this.properites.set(key.replace(/^##/g, ""), this._arbFileObject[key]);
});
}
}
module.exports = ArbFile;
at that point
console.log(JSON.stringify(this.ressources));
this.ressources is an empty map. I don't know why. In the debugger I can clearly see, that is has 55 entries. I have already tried to log for example the Object.keys() of it, but it is an empty Array too.
The arbFile parameter at the constructor is an path to an json-like ARB file.
To call that class, I create an new instance of ArbFile and then call read() on it.
Well here's why. This is Chrome console output. I'm really surprised, but apparently you cannot JSON.stringify a map!
var m = new Map();
m.set("a", undefined)
Map(1)Â {"a" => undefined}
m.set("b", "B")
Map(2)Â {"a" => undefined, "b" => "B"}
m
Map(2)Â {"a" => undefined, "b" => "B"}
JSON.stringify(m)
"{}"
Instead, try just logging the map directly without JSON.stringify.
I'm setting up a searchbar in a web app, and I've got most of it done(i.e. it's successfully finding the objects that I'm looking for), however, a dispatch at the end of the searchbar code. This is being built using Javascript, React and Redux. I'm entirely new to react, and my teams React guy is off for the week, so any help would be a massive help.
searchInList = (e) => {
const { dispatch, employees } = this.props;
const valueSearched = e.target.value;
let currentList = [];
let newList = [];
if (valueSearched !== ' ') {
currentList = employees;
currentList.map(employeeObject => {
Object.values(employeeObject).filter(item => {
let itemString;
if (typeof (item) != 'string') {
itemString = JSON.stringify(item);
} else {
itemString = item;
}
let lc = itemString.toLowerCase();
const filter = valueSearched.toLowerCase();
if (lc.includes(filter)) {
if (!newList.includes(employeeObject)) {
newList.push(employeeObject);
}
}
});
});
} else {
newList = employees;
}
console.log(newList);
dispatch(onChangeEmployee('employees', newList));
};
This should just narrow down the amount of objects being displayed (within the search terms), but it crashes and throws up this error: "TypeError: Cannot set property 'employees' of undefined".
It crashes on the dispatch(onChangeEmployee('employees', newList)); line
From
Cannot set property 'employees' of undefined
I can see you do something like
var a
a.employees='hello'
However, you never refer employees property of an object in the snippet presented
So the chance is high that the error is from onChangeEmployee
So basically, I have a web application that retrieves data from Firebase using rxjs observables.
here's my code,
initializeItems(){
this.travelList$ = this.plsdala.getTravelList()
.snapshotChanges()
.map(
changes => {
return changes.map(c=>({
key: c.payload.key, ...c.payload.val()
})).slice().reverse();//to reverse order
})
this.travelList$.subscribe(res => {
for(let i=0;i<res.length;i++){
this.ListOfitems.push (res[i].toAddress);
}
})
}
this is called from the constructor. problem here is that i cannot check if it is push successfully and if try to print in console , it wont print. why?
the element pushed is needed for filtering. heres is the code for filtter. but when i print the this.ListOfitems in console it is undefined and im wondering unto why? when the elements are initialized first
getItems(ev: any) {
console.log("awdaw");
console.log(this.ListOfitems);
if (this.ListOfitems.length>1){
console.log("otin");
let val = ev.target.value;
if (val && val.trim() != '') {
this.ListOfitems = this.ListOfitems.filter((ListOfitems) => {
return (ListOfitems.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
}
}
when you are declaring list of items if you want to push into the array you need to declare it empty first like this:
ListOfitems: string[] = [];
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
So I am trying to get data with AsyncStorage.getItem and then pass it to a function in React-native. but when I do that I get this error "data.filter is not a function" from my function. I think that the problem could be that I am not getting the data but insted a promise.
Constructor:
constructor(props) {
super(props)
const getSectionData = (dataBlob, sectionId) => dataBlob[sectionId];
const getRowData = (dataBlob, sectionId, rowId) => dataBlob[`${rowId}`];
const ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 !== r2,
sectionHeaderHasChanged : (s1, s2) => s1 !== s2,
getSectionData,
getRowData,
});
let data = AsyncStorage.getItem('connections').then((token) => {
token = JSON.parse(token);
return token;
});
const {dataBlob, sectionIds, rowIds} = this.formatData(data);
// Init state
this.state = {
dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, rowIds),
left: true,
center: false,
right: false
}
}
Function:
formatData(data) {
// We're sorting by alphabetically so we need the alphabet
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
// Need somewhere to store our data
const dataBlob = {};
const sectionIds = [];
const rowIds = [];
// Each section is going to represent a letter in the alphabet so we loop over the alphabet
for (let sectionId = 0; sectionId < alphabet.length; sectionId++) {
// Get the character we're currently looking for
const currentChar = alphabet[sectionId];
// Get users whose first name starts with the current letter
const users = data.filter((user) => user.nickname.toUpperCase().indexOf(currentChar) === 0);
// If there are any users who have a first name starting with the current letter then we'll
// add a new section otherwise we just skip over it
if (users.length > 0) {
// Add a section id to our array so the listview knows that we've got a new section
sectionIds.push(sectionId);
// Store any data we would want to display in the section header. In our case we want to show
// the current character
dataBlob[sectionId] = { character: currentChar };
// Setup a new array that we can store the row ids for this section
rowIds.push([]);
// Loop over the valid users for this section
for (let i = 0; i < users.length; i++) {
// Create a unique row id for the data blob that the listview can use for reference
const rowId = `${sectionId}:${i}`;
// Push the row id to the row ids array. This is what listview will reference to pull
// data from our data blob
rowIds[rowIds.length - 1].push(rowId);
// Store the data we care about for this row
dataBlob[rowId] = users[i];
}
}
}
return { dataBlob, sectionIds, rowIds };
}
So my question is once I have the promise what should I do with it in order to pass it to my function and make this line work const users = data.filter((user) => user.nickname.toUpperCase().indexOf(currentChar) === 0);?
Yea you're not waiting for the promise to resolve, you can either turn the outer function in an async function and await for data to be resolved or whatever you put in the .then gets ran after the promise resolves. Also moving into componentDidMount. You might also want to look into FlatList instead of ListView:
componentDidMount(){
AsyncStorage.getItem('connections').then((token) => {
const token = JSON.parse(token);
const {dataBlob, sectionIds, rowIds} = this.formatData(token);
// Update State
this.setState({
dataSource: ds.cloneWithRowsAndSections(dataBlob, sectionIds, rowIds)
});
});
}