I’m trying to build a react app that exports a DnD 5e character sheet. There are different bonuses based on your selected race/species. I have a dropdown menu to select your race and I want to apply the bonus to the appropriate stat. The problem is that if I then select a different option it doesn’t revert the stats. So if I click "Orc" I get a +1 to strength, but if I change it to "Elf", I get a +1 to intelligence but the +1 to strength sticks around and going back to "Orc" adds another +1 to strength. Any advice on setting these conditional bonuses?
Here is the function that assigns the stat values
<div>
{standardArray.map((stat, index) => {
return (
<div key={index}>
<Text marginLeft={5}> {stat.name[index]}</Text>
<Select
placeholder={stat.name[index]}
width="90%"
marginLeft={3}
marginBottom={3}
onChange={handleChange}
name={"playerStat" + [index]}
>
Name: {stat.name}
{stat.value.map((value, index) => {
return (
<option key={index} value={value}>
{value}
</option>
);
})}
</Select>
</div>
);
})}
</div>
This is the dropdown menu that calls the bonus function
<Select
placeholder="Choose a Species"
color={"White"}
marginLeft={3}
marginRight={3}
width="90%"
onChange={handleSpeciesChange}
value={state.playerSpecies}
name="playerSpecies"
>
<option value="Orc">Orc</option>
<option value="Elf">Elf</option>
<option value="Human">Human</option>
</Select>
This is the function that applies the bonus
const speciesBonus = (value: string) => {
if (value === "Orc") {
const speciesBonus = 1;
state.playerStat0 = parseInt(state.playerStat0) + speciesBonus;
}
if (value === "Elf") {
const speciesBonus = 1;
state.playerStat3 = parseInt(state.playerStat3) + speciesBonus;
} else {
state.playerStat0 = parseInt(state.playerStat0);
}
};
[1]: https://i.sstatic.net/Ia3mceWk.png
[2]: https://i.sstatic.net/Yjdc48hx.png
[3]: https://i.sstatic.net/ICMR3tWk.png
2
Answers
I’m going to answer from a RPG perspective, as much as from a tech perspective.
Species selection impacts more than just base stats. You’re going to want a record of which specie the character belongs to long-term, for things like racial abilities, or for some wild situations like Reincarnate.
Instead of directly updating the character’s stats, add the selected specie as a data field that you store itself. Then use something similar your
speciesBonus
to determine the correct value to display for each stat, without actually updating it on the state.As a side effect, doing this will solve your tech issue.
For completeness, though, your issue stems from the fact that your
speciesBonus
function only applies the new species bonus. If you wanted to update it with this same structure, you would need to changespeciesBonus
signature to accept both acurrent
andprevious
species, so you could "undo" the previous selection’s benefits.You could try to store the species bonuses in an object with key: speciesName, value: bonusesArray
Each time the user selects a species, you are going to:
For this you will need a state variable like "currentSelectedSpecies" to store the currently selected species.
I modified handleSpeciesChange to do that. I tried to only call setState once, so I got rid of the separate function.
Warning. I’ve not used setState before and none of this code is tested.