React: input value not defined in form

Viewed 642

I am trying to make a form that will submit to my API. However, after adding some nested keys, it says that the value is not defined. Also only for the form inputs that call the nested keys, I am not able to type any text in the input field. I have an onChange handler so that should allow text to be typed.

The relevant code is below. My issue is stemming from the "address: {...}" keys.

Any ideas would be greatly appreciated!

const [formState, setFormState] = useState({
    photo: '',
    address: {
        street: '',
        city: '',
        state: '',
        zip: '',
    },
    price: '',
    sqft: '',
    bed: '',
    bath: '',
    additionalDetails: {
        ac: false,
        laundry: false,
        garage: false,
        offStreetParking: false,
        fireplace: false,
        pool: false,
        hardwoodFloors: false,
        sewer: false,
        schoolsNearby: false,
        parksNearby: false,
    }
});

function handleChange(event) {
    setFormState(prevState => ({
        ...prevState,
        [event.target.name]: event.target.value
    }));
};

async function handleSubmit(event) {
    try {
        event.preventDefault();

        setFormState(event);
        await createListing(formState);
        props.history.push('/dashboard');
        props.refresh();
    } catch (error) {
        alert(error.message);
    };
};

return(
    <div>
        <div className={styles.CreateListingHeader} >
            <h1>C R E A T E &nbsp; A &nbsp; L I S T I N G</h1>
        </div>
        <div className={styles.CreateListingMain}>
            <div className={styles.CreateFormMain}>
                <form className={styles.CreateListingForm} onSubmit={handleSubmit}>
                    <div className={styles.CreateFormItem}>
                        <input
                            className={styles.CreateFormInput}
                            value={formState.photo}
                            onChange={handleChange}
                            type='text' 
                            name='photo' 
                            placeholder=' P H O T O &nbsp; L I N K'
                        />
                    </div>
                    <div className={styles.CreateFormItem}>
                        <div className={styles.CreateFormAddressItem}>
                            <input 
                                className={styles.CreateFormInput}
                                value={formState.address.street}
                                onChange={handleChange}
                                type='text' 
                                name='street' 
                                placeholder=' S T R E E T'
                            />
                            <input
                                className={styles.CreateFormInput}
                                value={formState.address.city}
                                onChange={handleChange}
                                type='text' 
                                name='city' 
                                placeholder=' C I T Y'
                            />
                            <input
                                className={styles.CreateFormInput}
                                value={formState.address.state}
                                onChange={handleChange}
                                type='text' 
                                name='state' 
                                placeholder=' S T A T E'
                            />
                            <input
                                className={styles.CreateFormInput}
                                value={formState.address.zip}
                                onChange={handleChange}
                                type='text' 
                                name='zip' 
                                placeholder=' Z I P'
                            />
                        </div>

// ...

2 Answers

You can try handleChange function with following method also. Just take fromState variable data and spread it in setFormState with the updated property name by specifying [event.target.name] and its value, It will update your state.

function handleChange(event) {
    setFormState({
           ...formState,
        [event.target.name]: event.target.value
    });
};

You could set the name of the input element for nested fields like 'address.street', not 'street'.

<input 
  className={styles.CreateFormInput}
  value={formState.address.street}
  onChange={handleChange}
  type='text' 
  name='address.street' 
  placeholder=' S T R E E T'
/>

And then use lodash functions in handleChange()

import _ from 'lodash';

...

function handleChange(event) {
  const newFormState = _.cloneDeep(formState)
  _.set(newFormState, event.target.name, event.target.value)
  setFormState(newFormState);
};
Related