Reusing variables later as integers/text later - javascript

I have tried getting cypress to save a text for later usage but I feel unable to reuse it as a variable
cy.get('.unrd').then(($span) => {
const filteredunread = $span.text()
cy.wrap(filteredunread).as('oldunreadmessage');
})
Codeblock to send a mail, wait and return to the inbox expecting an echo reply
cy.get('.unrd').then(($span) => {
cy.get('#oldunreadmessage') //seen as object
const newunread = $span.text()
expect(newunread).to.eq(cy.get('#oldunreadmessage') +1)
})
This gives me errors such as:
expected '(27)' to equal '[object Object]1'
I have tried to use .as(). However I seem to be unable to properly resolve my old object as a text or integer constant.

The first part is fine, but because of the cy.wrap you need to use should or then on the cy.get('#oldunreadmessage')
cy.get('.unrd').then(($span) => {
const newunread = $span.text();
cy.get('#oldunreadmessage').should('have.text', newunread);
})
or
cy.get('.unrd').then(($span) => {
const newunread = $span.text();
cy.get('#oldunreadmessage').then((oldunread) => {
expect(newunread)...
}
})

Related

Function throws error when trying to run a second time

I have a problem with a download button. If I reload the page, the onClick={() => ExportAll(data)} works fine the first time when pressing the download button, however when I try it after that the console throws this error:
The function itself looks like this:
const exportAll = (data) => {
const arr = []
data.map((element) => {
element.orderlines = element?.orderlines?.join(' , ')
arr.push(element)
}
);
exportFileAsXLSX(arr, `Meest recente orders-${props.timespan}`);
};
The data object is set using the useState hook
If anyone has any idea why this doesn't work, please let me know!
const exportAll = (data) => {
const arr = []
data.map((element) => {
let newElement = { ...element}
newElement.orderlines = element?.orderlines?.join(' , ')
arr.push(newElement)
}
);
exportFileAsXLSX(arr, `Meest recente orders-${props.timespan}`);
};
At first execution you overwrite original objects orderlines field value. Then at the next time you try to apply join operation to that field value again. Now it is a string not an array. That is the reason for the error.Change the code as above it will work.Above code I create a new obj rather than overwriting it.
Is orderlines an array? Cause you can only use join() if it is indeed an array!
Double check if it's not an object.

React, component not re-rendering after change in an array state (not the same as others)

I'm trying to make a page that gets picture from a server and once all pictures are downloaded display them, but for some reason the page doesn't re-render when I update the state.
I've seen the other answers to this question that you have to pass a fresh array to the setImages function and not an updated version of the previous array, I'm doing that but it still doesn't work.
(the interesting thing is that if I put a console.log in an useEffect it does log the text when the array is re-rendered, but the page does not show the updated information)
If anyone can help out would be greatly appreciated!
Here is my code.
export function Profile() {
const user = JSON.parse(window.localStorage.getItem("user"));
const [imgs, setImages] = useState([]);
const [num, setNum] = useState(0);
const [finish, setFinish] = useState(false);
const getImages = async () => {
if (finish) return;
let imgarr = [];
let temp = num;
let filename = "";
let local = false;
while(temp < num+30) {
fetch("/get-my-images?id=" + user.id + "&logged=" + user.loggonToken + "&num=" + temp)
.then(response => {
if(response.status !== 200) {
setFinish(true);
temp = num+30;
local = true;
}
filename = response.headers.get("File-Name");
return response.blob()
})
.then(function(imageBlob) {
if(local) return;
const imageObjectURL = URL.createObjectURL(imageBlob);
imgarr[temp - num] = <img name={filename} alt="shot" className="img" src={imageObjectURL} key={temp} />
temp++;
});
}
setNum(temp)
setImages(prev => [...prev, ...imgarr]);
}
async function handleClick() {
await getImages();
}
return (
<div>
<div className="img-container">
{imgs.map(i => {
return (
i.props.name && <div className="img-card">
<div className="img-tag-container" onClick={(e) => handleView(i.props.name)}>{i}</div>
<div className="img-info">
<h3 className="title" onClick={() => handleView(i.props.name)}>{i.props.name.substr(i.props.name.lastIndexOf("\\")+1)}<span>{i.props.isFlagged ? "Flagged" : ""}</span></h3>
</div>
</div>
)
})}
</div>
<div className="btn-container"><button className="load-btn" disabled={finish} onClick={handleClick}>{imgs.length === 0 ? "Load Images" : "Load More"}</button></div>
</div>
)
}
I think your method of creating the new array is correct. You are passing an updater callback to the useState() updater function which returns a concatenation of the previous images and the new images, which should return a fresh array.
When using collection-based state variables, I highly recommend setting the key property of rendered children. Have you tried assigning a unique key to <div className="img-card">?. It appears that i.props.name is unique enough to work as a key.
Keys are how React associates individual items in a collection to their corresponding rendered DOM elements. They are especially important if you modify that collection. Whenever there's an issue with rendering collections, I always make sure the keys are valid and unique. Even if adding a key doesn't fix your issue, I would still highly recommend keeping it for performance reasons.
It is related to Array characteristics of javascript.
And the reason of the console log is related with console log print moment.
So it should be shown later updated for you.
There are several approaches.
const getImages = async () => {
... ...
setNum(temp)
const newImage = [...prev, ...imgarr];
setImages(prev => newImage);
}
const getImages = async () => {
... ...
setNum(temp)
setImages(prev => JOSN.parse(JSON.object([...prev, ...imgarr]);
}
const getImages = async () => {
... ...
setNum(temp)
setImages(prev => [...prev, ...imgarr].slice(0));
}
Maybe it could work.
Hope it will be helpful for you.
Ok the problem for me was the server was not sending a proper filename header so it was always null so the condition i.props.name was never true... lol sorry for the confusion.
So the moral of this story is, always make sure that it's not something else in your code that causes the bad behavior before starting to look for other solutions...

React / ES6 - Efficiently update property of an object in an array

I am looking for the most efficient way to update a property of an object in an array using modern JavaScript. I am currently doing the following but it is way too slow so I'm looking for an approach that will speed things up. Also, to put this in context, this code is used in a Redux Saga in a react app and is called on every keystroke* a user makes when writing code in an editor.
*Ok not EVERY keystroke. I do have debounce and throttling implemented I just wanted to focus on the update but I appreciate everyone catching this :)
function* updateCode({ payload: { code, selectedFile } }) {
try {
const tempFiles = stateFiles.filter(file => file.id !== selectedFile.id);
const updatedFile = {
...selectedFile,
content: code,
};
const newFiles = [...tempFiles, updatedFile];
}
catch () {}
}
the above works but is too slow.
I have also tried using splice but I get Invariant Violation: A state mutation
const index = stateFiles.findIndex(file => file.id === selectedFile.id);
const newFiles = Array.from(stateFiles.splice(index, 1, { ...selectedFile, content: code }));
You can use Array.prototype.map in order to construct your new array:
const newFiles = stateFiles.map(file => {
if (file.id !== selectedFile.id) {
return file;
}
return {
...selectedFile,
content: code,
};
});
Also, please consider using debouncing in order not to run your code on every keystroke.

Struggling to pass props through navigation, I believe it has something to do with my AysncyStorage set multiple

I'm trying to pass some values into another screen, it worked the first time when I tried it with one value, using async storage set for a single item, however, now I am trying it with multiple and it keeps crashing every time I press the item I want to get the data from.
Storing the data when I press on an item from a FlatList
fetchOnPressOpacity = async item => {
this.state.totalCalories += item.food.nutrients.ENERC_KCAL;
this.state.totalFat += item.food.nutrients.FAT;
this.state.totalCarbs += item.food.nutrients.CHOCDF;
this.state.totalProtein += item.food.nutrients.PROCNT;
const firstPair = ["totalCalories", JSON.stringify(this.state.totalCalories)];
const secondPair = ["totalCarbs", JSON.stringify(this.state.totalCarbs)];
const thirdPair = ["totalProtein", JSON.stringify(this.state.totalProtein)];
const fourthPair = ["totalFat", JSON.stringify(this.state.totalFat)];
try {
this.setState({});
await AsyncStorage.multiSet(firstPair, secondPair, thirdPair, fourthPair);
} catch (error) {
console.log(error);
}
};
getData() method, I am not too sure how to store the data:
getData = async () => {
try {
const values = await AsyncStorage.multiGet([
"totalCalories",
"totalCarbs",
"totalProtein",
"totalFat"
]);
} catch (e) {
// read error
}
console.log(values);
};
So, right now my main problem is that the application crashes when I press an item.
I get the below error, but do not think this is the issue.
VirtualizedList: missing keys for items, make sure to specify a key or
id property on each item or provide a custom keyExtractor.
I am also able to write to the console the value before the app crashes.
Could you please advise me?
Simple solution
var items = [['key1', 'value1'], ['key2', 'value2']]
AsyncStorage.setItem("DATA_KEY", JSON.stringify(items))
// or
AsyncStorage.multiSet(items, () => {
//to do something
});
For your code
var items = [firstPair, secondPair, thirdPair, fourthPair];
AsyncStorage.setItem("DATA_KEY", JSON.stringify(items))
Get data
AsyncStorage.multiGet(["key1", "key2"]).then(response => {
//to do something
})
Not really a fix to your code but if it's just to pass data to another screen, you could consider to pass data with navigation.
like:
const { navigation } = this.props;
navigation.navigate('YourNextScreen',
{
totalCalories: this.state.totalCalories,
totalCarbs: this.state.totalCarbs,
totalProtein: this.state.totalProtein,
totalFat: this.state.totalFat,
});
and retrieve them in:
const {
totalCalories,
totalCarbs,
totalProtein,
totalFat
} = this.props.route.params;
in case you don't want to specifically save those data for later...
https://reactnavigation.org/docs/params/

Get the ChildrenCount of a child in Firebase using JavaScript

I have been doing this for an hour. I simply want to get the number of children in the child "Success" in the database below. The answers in similar stackoverflow questions are not working. I am new in Javascript Programming.
So far I have tried this
var children = firebase.database().ref('Success/').onWrite(event => {
return event.data.ref.parent.once("value", (snapshot) => {
const count = snapshot.numChildren();
console.log(count);
})
})
and also this
var children = firebase.database().ref('Success/').onWrite(event => {
return event.data.ref.parent.once("value", (snapshot) => {
const count = snapshot.numChildren();
console.log(count);
})
})
Where might I be going wrong.
As explained in the doc, you have to use the numChildren() method, as follows:
var ref = firebase.database().ref("Success");
ref.once("value")
.then(function(snapshot) {
console.log(snapshot.numChildren());
});
If you want to use this method in a Cloud Function, you can do as follows:
exports.children = functions.database
.ref('/Success')
.onWrite((change, context) => {
console.log(change.after.numChildren());
return null;
});
Note that:
The new syntax for Cloud Functions version > 1.0 is used, see https://firebase.google.com/docs/functions/beta-v1-diff?authuser=0
You should not forget to return a promise or a value to indicate to the platform that the Cloud Function execution is completed (for more details on this point, you may watch the 3 videos about "JavaScript Promises" from the Firebase video series: https://firebase.google.com/docs/functions/video-series/).
const db = getDatabase(app)
const questionsRef = ref(db, 'questions')
const mathematicalLiteracy = child(questionsRef, 'mathematicalLiteracy')
onValue(mathematicalLiteracy, (snapshot) => {
const data = snapshot.val()
const lenML = data.length - 1
console.log(lenML)
})
This method worked for me. I wanted to get the children's count of the mathematicalLiteracy node in my database tree. If I get its value using .val() it returns an array that contains that node's children and an extra empty item. So, I subtracted that one empty item's count. Finally, I get my needed children's count.

Categories

Resources