React state question

Hi, I've been stuck on this for a few hours now but I can't figure it out. https://codesandbox.io/s/practical-beaver-vgcmcv?file=/src/App.js I basically map over an array of items and for each item I made an input to fill in a value of the item. Filling in a value for this item should do 2 possible things: Make a new object with the e.target.name, e.target.value and object.amount or Update the value in an existing object (if this value has previously been filled in)
CodeSandbox
practical-beaver-vgcmcv - CodeSandbox
practical-beaver-vgcmcv using loader-utils, react, react-dom, react-scripts
13 Replies
aevitas
aevitas•2y ago
I've commented out some other stuff I have tried (I left out the 500 variations of it though) 😄
vince
vince•2y ago
I look at this in about an hour Can you explain a bit what you need with psuedocode and some dummy values? I see that you did in your code but I'm still a bit confused
aevitas
aevitas•2y ago
Well basically I map over an array of items, each item will create an input. If you fill in a value here, setState should add: name: e.target.name, amount: item.amount, value: e.target.value But if the array already contains an item with this name, it should just update the value So if test input box contains 5, a input has 10, b input has 100 then the array should be:
[
{
name: "test",
amount: "25",
value: "5",
},
{
name: "a",
amount: "2",
value: "10",
},
{
name: "b",
amount: "15",
value: "100",
},
]
[
{
name: "test",
amount: "25",
value: "5",
},
{
name: "a",
amount: "2",
value: "10",
},
{
name: "b",
amount: "15",
value: "100",
},
]
And when you change the input of test, only the value of test should be changed. The rest of the array should remain I hope this makes sense
vince
vince•2y ago
Oh I see, thanks for clarifying! I'll see if I can make heads or tails of it for you
aevitas
aevitas•2y ago
Thanks ! 🙂 Curious what the solution is..
vince
vince•2y ago
I do not like this solution personally, but it works Basically, every time an input has a change, it copies the state array and modifies the object, and then sets the state to the new copy with the updated value As you can imagine, this will probably be super inefficient with a more complex application... but I'm not skilled enough to know of a better solution
aevitas
aevitas•2y ago
This indeed seems to work fine in this case, but in mine the inputs variable will be empty (there won't be any items added there), how would this work if the item doesn't exist and it has to add a new one? There's approx 70 different items and I rather not add them manually to the initialInputs variable 😄 That would make for some real messy code..
vince
vince•2y ago
For sure haha, let me see... Oh I think I see what you're saying, are you getting the input data from an api or do you just manually have 70 different input objects? The best bet, if I'm understanding correctly, is to make a separate component that takes a few different props (namely: name, value, amount) and creates a new input field Then you can map each object in the array to this Input component
aevitas
aevitas•2y ago
Not from an API, just my own json 🙂 https://tibia-calculator.netlify.app/imbuement-calculator It's for this calculator Data for the first imbuement (scorch) is:
{
"name": "Scorch",
"image": "Basic_Scorch",
"amount": 10,
"type": "physical converted to fire damage",
"materials": [
{ "name": "Fiery Hearts", "amount": 25, "image": "Fiery_Heart" }
]
},
{
"image": "Intricate_Scorch",
"amount": 25,
"type": "physical converted to fire damage",
"materials": [
{ "name": "Fiery Hearts", "amount": 25, "image": "Fiery_Heart" },
{
"name": "Green Dragon Scales",
"amount": 5,
"image": "Green_Dragon_Scale"
}
]
},
{
"image": "Powerful_Scorch",
"amount": 50,
"type": "physical converted to fire damage",
"materials": [
{ "name": "Fiery Hearts", "amount": 25, "image": "Fiery_Heart" },
{
"name": "Green Dragon Scales",
"amount": 5,
"image": "Green_Dragon_Scale"
},
{ "name": "Demon Horns", "amount": 5, "image": "Demon_Horn" }
]
},
{
"name": "Scorch",
"image": "Basic_Scorch",
"amount": 10,
"type": "physical converted to fire damage",
"materials": [
{ "name": "Fiery Hearts", "amount": 25, "image": "Fiery_Heart" }
]
},
{
"image": "Intricate_Scorch",
"amount": 25,
"type": "physical converted to fire damage",
"materials": [
{ "name": "Fiery Hearts", "amount": 25, "image": "Fiery_Heart" },
{
"name": "Green Dragon Scales",
"amount": 5,
"image": "Green_Dragon_Scale"
}
]
},
{
"image": "Powerful_Scorch",
"amount": 50,
"type": "physical converted to fire damage",
"materials": [
{ "name": "Fiery Hearts", "amount": 25, "image": "Fiery_Heart" },
{
"name": "Green Dragon Scales",
"amount": 5,
"image": "Green_Dragon_Scale"
},
{ "name": "Demon Horns", "amount": 5, "image": "Demon_Horn" }
]
},
Problem is there's 69 different combinations (scorch has 3, basic, intricate and powerful) so it would be hell to make all that manually
vince
vince•2y ago
If you have your own json you can read it and iterate through it My Input component would allow for that, you just need to write the logic to loop through it and map each entry in your json to an Input
aevitas
aevitas•2y ago
I finally got it It's just like my initial example, except the onchange now is:
onChange={(e) =>
setValue(value.filter((obj) => obj.name !== item.name).concat({
name: item.name,
amount: item.amount,
value: e.target.value,
})
)
}
onChange={(e) =>
setValue(value.filter((obj) => obj.name !== item.name).concat({
name: item.name,
amount: item.amount,
value: e.target.value,
})
)
}
Thank you for the help though! 🙂
Want results from more Discord servers?
Add your server