Search code examples
reactjstypescriptformsselectinput

How to type a value from select and input in react form


Trying to write an app to store cocktail recipes. I have a problem with types for a single line in a form consisting of select and input.

How do I o type read the data from the form.

Parent Component

const [formIngradient, setFormIngradient] = useState<CoctailIngredients[]>([
        {
            ingredient: '',
            quantity: 0,
        }
    ])

    const handleFormChange = (index: number, event: ChangeEvent<HTMLSelectElement | HTMLInputElement>) => {
        const {name, value} = event.currentTarget
        let data = [...formIngradient];
        data[index][name] = value
        setFormIngradient(data)
    }


<form onSubmit={sendForm}>
            {formIngradient.map((form, index) => {
                return (
                    <p className='ingredient__single__input'>
                        <ChoiceOfIngredient 
                         productList={productList} 
                         handleFormChange={handleFormChange} 
                         index={index} 
                         inputRow={form}
                        />
                    </p>
                )
            })}      
        </form>

Child Component

interface Props {
    productList: ProductEntity[];
    handleFormChange: (index: number, event: ChangeEvent<HTMLSelectElement | HTMLInputElement>) => void;
    index: number;
    inputRow: CoctailIngredients;
}

export const ChoiceOfIngredient = (props: Props) => {

    return (
        <p className='ingredient__p'>
            <FormControl fullWidth sx={{mr: 2}} key={props.index}>
                <InputLabel id="demo-simple-select-label">Ingredient {props.index + 1}</InputLabel>
                <Select
                    labelId="demo-simple-select-label"
                    id="demo-simple-select"
                    label="ingredient"
                    name={`ingredient`}
                    value={props.inputRow.ingredient}
                    onChange={event => props.handleFormChange(props.index, event)}
                >
                    {
                        props.productList.map(product =>
                            <MenuItem
                                key={product.id}
                                value={product.id}
                            >{product.name}</MenuItem>
                        )
                    }
                </Select>
            </FormControl>
            <TextField
                id="outlined-number"
                label="ml"
                type="number"
                InputLabelProps={{
                    shrink: true,
                }}
                name={`quantity`}
                value={props.inputRow.quantity}
                onChange={event => props.handleFormChange(props.index, event)}
            />
        </p>
    )
}

Because using such a solution returns me an error

TS2345: Argument of type 'ChangeEvent<HTMLInputElement | HTMLTextAreaElement>' is not assignable to parameter of type 'ChangeEvent<HTMLSelectElement | HTMLInputElement>'.
  Type 'HTMLInputElement | HTMLTextAreaElement' is not assignable to type 'HTMLSelectElement | HTMLInputElement'.
    Type 'HTMLTextAreaElement' is not assignable to type 'HTMLSelectElement | HTMLInputElement'.
      Type 'HTMLTextAreaElement' is missing the following properties from type 'HTMLInputElement': accept, align, alt, capture, and 27 more.
    47 |                 name={`quantity`}
    48 |                 value={props.inputRow.quantity}
  > 49 |                 onChange={event => props.handleFormChange(props.index, event)}
       |                                                                        ^^^^^
    50 |             />
    51 |         </p>
    52 |     )

Próbowałem zmieniać i wstawiać różne typy ale za każdym razem pokazuje błąd. Ja już nie wiem jak to o typować aby było dobrze.


Solution

  • OK. I managed to solve this problem. This is my solution.

    event: ChangeEvent<HTMLInputElement| HTMLTextAreaElement > |  SelectChangeEvent<string>