I am working with some data and trying to populate a form dynamically. It works as I expected except when it comes to an array for one of the dropdowns. For some reason it will log to the console but not update the options.
import React, { useReducer} from 'react'
import { Container } from 'react-bootstrap';
import Products from '../data/Products';
import { v4 as uuidv4 } from 'uuid';
const ProductForm= () => {
const useReducerState = (initialState = {}) => {
const reducer = (prev, next) => ({ ...prev, ...next });
return useReducer(reducer, initialState);
};
const [state, setState] = useReducerState({
make: "",
model: "",
storage: "",
color: "",
});
const handleChange = (e) => {
let proToUpdate = e.target.name;
let value = e.target.value;
if (value){setState({ [proToUpdate]: value }); }
}
const {
make,
model,
storage,
color,
} = state;
return (
<Container>
<form autoComplete='off'>
<div className="form-group">
<select name="make" className="hardwear" id="make" value={make} required onChange={handleChange}>
<option value="">Manufacturer</option>
{ Object.keys(Products["handset"]["hardwear"]).map(item => {
return (<option value={item} key={uuidv4()}>{item}</option>);
})}
</select>
<select name="model" id="model" className="hardwear" value={model} onChange={handleChange}>
<option value="">Model</option>
{ make && ( Object.keys(Products["handset"]["hardwear"][state.make]).map(item => {
return (<option value={item} key={uuidv4()}>{item}</option>);
}))}
</select>
<select name="storage" className="hardwear" value={storage} onChange={handleChange}>
<option value="">Storage</option>
{ model && (Products["handset"]["hardwear"][state.make][state.model]["storage"].forEach(item => {
console.log(item)
return (<option value={item} key={uuidv4()}>{item}</option>);
}))}
</form>
</Container>
)
}
The issue is the storage option. As I said, it will log the value to the console but doesn't populate the dropdown. Here is the data I am using, which I cannot change for now.
const Products = {
"handset" : {
"hardwear":
{
"Apple": {
"iPhone 13": {
"color": ["Blue","Pink","Midnight","Red","Starlight"],
"storage": ["128GB", "256GB", "512GB"],
},
"iPhone 13 Pro": {
"color": ["Sierra Blue","Gold","Graphite","Silver"],
"storage": ["128GB", "256GB", "512GB", "1 Terabyte"],
},
}}}}
CodePudding user response:
EDIT: You should use map instead of forEach.
In your options for storage select you put your item as a string. Remove the double quotes around item:
<select name="storage" className="hardwear" value={storage} onChange={handleChange}>
<option value="">Storage</option>
{ model && (Products["handset"]["hardwear"][state.make][state.model]["storage"].map(item => {
console.log(item)
return (<option value={item} key={uuidv4()}>{item}</option>);
})
)
}
</select>
It might be a copy paste error but you are also missing a closing select in your code.