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.
Related
Within my function, through interaction from the user, I aim slowly build up an array of responses which I then pass off to an API. However, different approaches to append to the array, simply return a single position array (overwrite).
My current code as follows:
const contribution: Array = [];
const handlePress = () => {
var col = {
response,
user: 1,
update: update.id,
question: q.id,
};
contribution = [...contribution, col];
}
My understanding is that contribution = [...contribution, col] is the correct way to add to the array.
What is the best practice approach for doing this inside a function called each time the user interacts?
Although it is not clear from the question, I suspect, this code is inside a component. If so, then a new contribution array is created on every render. You need to use useState to store this array so that a new array is not created on every render.
const [contribution, setContribution] = React.useState([]);
const handlePress = () => {
var col = {
response,
user: 1,
update: update.id,
question: q.id,
};
setContribution([...contribution, col]);
}
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)...
}
})
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/
I'm trying to pass a property, that is inside the first position of an array of objects, to another module so I can use this value later. I've tried to pass it as module(args), but it keeps reading the default value which is 0. Is there a way to do this?
I tried to implement some React.context but the Bot framework Emulator is refusing it.
/////////////////Module that ll acquire the value/////////////////////////////
getCard(bot, builder, params) {
let configValues = { ...params[0] }
bot.dialog(`${configValues.path}`, function (session) {
var msg = new builder.Message(session);
const cardItem = (obj) => {
return (new builder.HeroCard(session)
.title(`${obj.title}`)
.text(`R$ ${obj.price}`)
.images([builder.CardImage.create(session, `${obj.img}`)])
.buttons([
builder.CardAction.imBack(session, `${obj.price} Item adicionado!`, 'add to cart')
// !onClick event must add the current obj.price to
// the configValues.total(Ex: configValues.total += obj.price)!
])
)
}
msg.attachmentLayout(builder.AttachmentLayout.carousel)
msg.attachments(
eval(params.map(obj => cardItem(obj)))
);
//!in here before end the dialog is where i want to update
// the configValues.total so i can show it in the -> Checkout module
session.send(msg).endDialog()
}).triggerAction({ matches: configValues.regex });
}
}
//////////////CheckOut.Module///////////////////////////////
{...}
let configValues = { ...params[0] }
let state = {
nome: "",
endereco: "",
pagamento: "",
total: configValues.total // this is the value to be read
}
bot.dialog('/intent', [
{...},
(session, results) => {
state.pagamento = results.response
session.send(
JSON.stringify(state) // here is the place to be printed
)
{...}
]
).triggerAction({ matches: /^(finalizar|checar|encerrar|confirmar pedido|terminar)/i })
Since you solved your original problem, I'll answer the one in your comment.
Your problem is here:
cartId.map((obj, i , arr) => {
// if (!obj.total) {
// obj.total.reduce(i => i += i)
// }
const newtotal = new total
newtotal.getTotals(bot, builder, obj, arr)
})
cartId contains the totals for each of your items. When you call map on it, you're passing each item individually to getTotals, which passes each item to checkout()
The reason you can't sum all of the totals and can only sum one item's total is that you pass cartId to checkout and cartId has been changed to just a single item. Instead, there's a couple of different things you could do:
Pass the whole cartId from cartItems and use something like for (var key in cartItems) in totalConstructor() and checkoutConstructor(). This is probably the easiest, but not very memory efficient.
Use BotBuilder's State Storage to store your totals array in userData, then sum that at the end. This might be more difficult to implement, but would be a much better route to go. Here's a sample that can help you get started.
//It's working now - updated code
I'm working on my own autocomplete component because I have problem with passing firebase data to a ready one.
The whole mechanism is working good but I have problem with passing values after getting user input
I'm setting initial state with those values
const INITIAL_STATE = {
allChars: [],
suggestions: [],
value: ""
};
Then in autocomplete class i'm loading all users from database
loadData(){
let self = this;
let characters = firebase.firestore().collection("users");
characters.get().then((querySnapshot) => {
querySnapshot.forEach((doc) => {
let document = doc.data();
self.setState(({allChars})=>({
allChars: [
...allChars,
document
]
}))
});
});
}
Here is my getSuggestions function. It is firing on input change
getSuggestions = event => {
const {value, suggestions} = event.target;
this.setState({
value: value,
suggestions: []
})
let suggest = [];
this.state.allChars.map((allChars) => {
if(value.length > 1 && allChars.name.toLowerCase().includes(value.toLowerCase())){
suggest.push (
allChars.name
);
}
})
this.setState({
suggestions: suggest
})
}
In render I just put {sugestions}
But in {suggestions} I get rendered only one name.
one
But when I console.log it - I get two names
two
There should be two.
I tried to set state in this function like in loadData(), but I still get only one value.
Is there other way to get both values into DOM
Full code can be found here: https://github.com/Ilierette/react-planner/blob/master/src/component/elements/Autocomplete.js
I think the reason you are just seeing one element each time your components re-render is that in your map function on your allChars array, when you want to update the suggestions in your state, you are setting just the name each time as a new array while you should update the existing array in your state, so your code should be:
this.setState({
suggestions: [...this.state.suggestions, allChars.name]
})