So I have the below code:
function Crafting(props) {
const craftItems = [
{
key: 1,
name: "Bronze sword",
},
{
key: 2,
name: "Iron sword",
},
{
key: 3,
name: "Steel sword",
},
];
const [item, setItem] = useState();
const [itemKey, setItemKey] = useState();
function onChangeHandler(event) {
setItem(event.target.value);
setItemKey(event.target.itemID);
console.log(event);
}
function onSubmitHandler(event) {
event.preventDefault();
console.log(item);
console.log(itemKey);
}
return (
<Card className={classes.renderwin}>
<form onSubmit={onSubmitHandler}>
<label htmlFor="items">Select an item</label>
<select name="items" onChange={onChangeHandler}>
{craftItems.map((item) => (
<option key={item.key} itemID={item.key}> {item.name} </option>
))}
</select>
<Button type="submit">Craft item</Button>
</form>
</Card>
);
}
I want to be able to retrieve the original key value against the item. I tried using "key", then added in a custom prop called "itemID" but they both just return as undefined. How do I fetch the ID back based on the value selection?
CodePudding user response:
The issue is that you can basically store only an option value and retrieve that in the handler to save into state.
I would place the item.key
on the option
element's value
attribute.
<select name="items" onChange={onChangeHandler}>
{craftItems.map((item) => (
<option key={item.key} value={item.key}>
{item.name}
</option>
))}
</select>
Access the onChange
event object's value
property in the handler and convert it back to a Number type before storing in state.
function onChangeHandler(event) {
const { value } = event.target;
setItemKey(Number(value));
}
When accessing in the submit handler use the stored itemKey
to search the craftItems
array for the matching object.
function onSubmitHandler(event) {
event.preventDefault();
const item = craftItems.find(({ key }) => key === itemKey);
console.log(item?.name);
console.log(item?.key);
}
function Crafting(props) {
const craftItems = [
{
key: 1,
name: "Bronze sword"
},
{
key: 2,
name: "Iron sword"
},
{
key: 3,
name: "Steel sword"
}
];
const [itemKey, setItemKey] = React.useState();
function onChangeHandler(event) {
const { value } = event.target;
setItemKey(Number(value));
console.log({ value });
}
function onSubmitHandler(event) {
event.preventDefault();
const item = craftItems.find(({ key }) => key === itemKey);
console.log(item && item.name);
console.log(item && item.key);
}
return (
// <Card className={classes.renderwin}>
<form onSubmit={onSubmitHandler}>
<label htmlFor="items">Select an item</label>
<select name="items" onChange={onChangeHandler}>
{craftItems.map((item) => (
<option key={item.key} value={item.key}>
{item.name}
</option>
))}
</select>
<button type="submit">Craft item</button>
</form>
// </Card>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<Crafting />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root" />
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Place a value on the option
like this:
{craftItems.map((item) => (
<option value={item.key} key={item.key}>{item.name}</option>
))}