Dynamic element from array - arrays

I want to dynamically update a element whenever the array it is based from changes.
//Dynamic Array - depositInfo[0] looks like:
//[{"tsR":1648183525,"durR":30,"amtR":10000000000000000}]
let depositInfo = [];
const depositCard = (card, index, amtR) => {
return (
<div key={index}>
<Text strong>
Value that doesn't update!:
{card.tsR}
{parseFloat(card.tsR)}
{JSON.stringify(depositInfo[index].tsR)}
<p />
Values that do update!:
{JSON.stringify(depositInfo[index])}
<p />
</Text>
</div>
);
};
The element is rendering on the page before the values are dynamically retrieved into the array, rendering it blank. After the array updates, the values on the page remain the same except for the ones generated by {JSON.stringify(depositInfo[index])}
How do I update the depositCard info every time depositInfo[] changes/is updated?
Edit:
Also why does depositInfo[index].tsR return a blank value when depositInfo[index] works fine?

Related

Get access to an array in an array from REST API

Hi I'm trying to display variants in two separate categories Color and Size, to do this I need to get data from the api, I can access "attributes", but I would like to be able to access 0 and 1 and map them, I have no idea how to do this.
{variants.length > 1 ? (
variants.attributes.map(({ name, values }) => (
<ProductOptions
key={`key-${name}`}
name={name}
values={values}
selectedOptions={selectedOptions}
setOptions={setOptions}
/>
))
) : (
<Fragment />
)}
Thank you so much!
As i understand the output of Array with 6 elements where each of that 6 has attributes and attributes is yet another array and you want to loop through those attributes so you need 2 loops. One to loop through parent array and seconds inside the child.
variants.map((variant) => {
variant.attributes.map((attribute) => {
console.log('attribute: ', attribute);
console.log('attribute id: ',attribute.id);
});
});
p.s. you may use forEach https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach but it has little difference in this case.
Also it seems like you working with ReactJS and building some JSX to put into rendered jsx. I would argue to form the array upfront and in final jsx just insert the rows, so your final jsx will be more readable, especially in cases of double loops or any more complex jsx.
const attributes = [];
variants.map((variant) => {
variant.attributes.map((attribute) => {
console.log('attribute: ', attribute);
console.log('attribute id: ',attribute.id);
attributes.push(<div key={attribute.id}>{attribute.id}</div>)
});
});
// later
return (
<div>
{attributes}
</div>
)

How to target only the last item in a v-for array?

I have an array of objects inside v-for to create a component for each item like so:
<div v-for="(expense, idx) in myExpenses" :key="idx">
<expense-panel
v-model.number="expense.expensesValue"
:expense="expense"
:myExpenses="myExpenses"
:showEdit="showEdit">
</expense-panel>
</div>
I have a method to add and extra "expense" to the array:
(I logged the item I am trying to specifically target)
addExpense() {
this.myExpenses.push({
expensesKey: "",
expensesValue: null,
subExpense: null,
});
//The last item in the array
console.log(this.myExpenses[this.myExpenses.length - 1]);
},
Is there a way in Vue to specifically add an input element to the last item of the array?
I have a showInput = false in the parent's Data() already.
You could for example add a slot to expense-panel and conditionally render your-input there only if it's the last item that is being rendered, like this:
<div v-for="(expense, idx) in myExpenses" :key="idx">
<expense-panel
v-model.number="expense.expensesValue"
:expense="expense"
:myExpenses="myExpenses"
:showEdit="showEdit">
<your-input v-if="idx === myExpenses.length - 1" />
</expense-panel>
</div>
Other alternative could be passing a prop to the panel (like is-last) and baking the input into the expense-panel.
Also, if the input should be rendered visually AFTER the last item, you can simply add input after the whole list:
<div v-for="(expense, idx) in myExpenses" :key="idx">
<expense-panel
v-model.number="expense.expensesValue"
:expense="expense"
:myExpenses="myExpenses"
:showEdit="showEdit">
</expense-panel>
</div>
<your-input />

Conditional classes on single instances of component within a loop

I have a loop of components that make a grid and I want some instances to have a background color change triggered by adding a class.
This question gave me ideas but I've yet to get them to work.
I have this basic markup in it.
<div className={`box ${(this.state.backgroundColor ? 'backgroundColor' : null)}`} key={i}>
</div>
And I have an array of the indexes representing the component instances that I want the color changed on
let indexes = [101, 178, 232, 545]
Currently I am doing it with plain JS, via document.querySelector('.box:nth-of-type(101'), but as this method bypasses React I want to change it.
Based on the other question I tried making an array of all the components and setting that to state, then looping through and using the indexes. I don't know how to "access" the component like this and get $$typeof: Symbol(react.element) etc
let compArr = []
this.arr.map((i) => {
compArr.push(
<div className={`box ${(this.state.backgroundColor ? 'backgroundColor' : null)}`} key={i}>
</div>
)
})
this.setState({
compArr: compArr
})
Then later loop over indexes:
indexes.map(index => {
this.state.compArr[index] ===> ??stuck here??
})
Expected Output: So on an array of three instances, say I want the second one only to have the class of backgroundColor:
<div className='box' </div>
<div className='box backgroundColor'</div>
<div className='box'</div>
Only in my case, I want the instances to correlate with the indexes array
How can I set the conditional class to true in those instances I have in the array? Say I have like 500+ instances total.
If I understand you correctly this is proably what you're looking for...
let indexes = [101, 178, 232, 545]
let compArr = this.arr.map((obj, i) => {
return (
<div
className={`box${( indexes.includes(i) ? " backgroundColor" : "")}`}
key={i}
>
</div>
);
})
this.setState({
compArr: compArr
})
If your goal is only to return the given div with the className backgroundColor for every element in this.arr with its index included in the indexes array then...
You only need to iterate over the array once and can perform all the necessary logic you're currently doing performing in two.
You don't need to use Array.push() to an outside collector when using any of the pure functions like map() or reduce() because they return a new version of whatever array is iterated over.
If for whatever reason you want a distinct array of <div>s with an index in indexes then you should use reduce...
let compArr = this.arr.reduce((acc, obj, i) => {
if (!indexes.includes(i)) return acc;
return [
...acc,
<div className="box backgroundColor" key={i}></div>
)]
},[])

React save the value of current state and make it unchangeable

I am new to React and I have a problem considering saving the value of current state. I am not sure if it is possible.
To summarise, I have build up a function which returns a HTML element as below. The idea is to save a div on each click.
createQuestion(){
let CurrentQuestion=this.state.freetextinput;
return this.state.values.map((el, i) =>
<div key={i} className="QuestionBox">
{CurrentQuestion}
</div>
)
}
The value of freetextinput changes on each click. The idea is to save all the value of freetextinput. Say, the values of freetextinput are 1, 2, 3. I would like to have all of the three values:
1
2
3
However, I only get something like this:
3
3
3
I wonder, if there is a way to save/store the value of this.state.freetextinput, such that I can get all the three values.
The new question needs to be pushed into an array before it can be mapped. Might something like this work for you?
var savedQuestions = []
createQuestion(q){
savedQuestions.push(q)
this.setState({savedQuestions: savedQuestions}, () => {
var questionElements = this.state.savedQuestions.map((el, i) =>
<div key={i} className="QuestionBox">
{el}
</div>
)
})
return questionElements
}
Save every input of free text input into an array, that way you would get access to all the values:
You can check this code sandbox: https://codesandbox.io/s/j835121kv
You should map this.state.freetextinput directly :
Since freetextinput is a string, you will need to convert it to an array first using split
createQuestion(){
return this.state.freetextinput.split(', ').map(el =>
<div key={el} className="QuestionBox">
{el}
</div>
)
}
This will work if your string looks like : "1, 2, 3"
If your string is "123" then use split('') instead of split(', ')

Reactjs, how to instanciate object from array, and update render

I'm struggling with reactjs for no reason. I'm a little confused about the magic behind and I'm not able to perform a simple operation of adding object / removing object from an array and display it.
I my parent, I have a method which on click append a new element:
appendNewPma(){
var newPma = this.state.pma.slice();
newPma.push(PmaType1);
this.setState({pma:newPma})
}
then my render method is like that:
render() {
return (
<div>
<a className="waves-effect waves-light btn" onClick={this.appendNewPma}>new</a>
{this.state.pma.map((Item, index) => (
<Item
key = {index}
ref = {"pma" + index.toString()}
onDelete = {() => this.onDelete(index)}
title = {index}/>
))}
</div>
);
}
Append work fine, but my array doesn't contain an object to display but rather a magical function that I don't understand.
But when I try to delete an object:
onDelete(idx){
console.log(idx);
var pma = this.state.pma.slice();
pma.splice(idx, 1);
this.setState({pma:pma})
}
When I delete from the array, no matter what index I will remove, it will only remove the last object. I know my code is not ok, but I have no idea how you can render element for an array of object (here my array is list of function constructor).
It will work better if I could get a straight ref to my object. Of course, I tryed to removed from the ReactDom, but was complening I was not updating from the parent...
I just want a simple array push/pop pattern with update.
Thanks for your help
Try below code. hope so it solve your issue.
addToArray = (event) => {
this.state.pma.push({"name ": "xyz"});
this.setState(
this.state
)
}
removeFromArray =(index) => {
var updatedArr = this.state.pma.splice(index, 1);
this.setState({arr : updatedArr})
}

Resources