Skip to content
Advertisement

How to add and remove multiple checkbox values and update nested array in React state hook

I am using React Context to create a multistep form, the form must keep the selection when the user clicks the next or previous step. I am using the below code and it’s working fine until I reach the stage to add multiple features using the checkbox, once items are checked, user can go to the previous step to edit and press next to go to the next stage where checked checkboxes must remain checked. I cannot figure out how to push each checkbox value to the features array and remove the item from array when the user uncheck. The important part is to retain the selected despite user go to previous or next step.

Context Provider

import React, { useEffect, useState, createContext } from 'react'

const carSpecs = {
    make: '', features: [],model: '',serviceHistory: false, warranty: false, trim: '', bodyType: '', transmission:''
}

export const UsedCarListingContext = createContext({})

export function GlobalUsedCarListingProvider (props) {
    const [usedCar, setUsedCar] = useState(carSpecs)
    useEffect(() => {}, [usedCar])

    return (
        <UsedCarListingContext.Provider
            value={[usedCar, setUsedCar]}
        >
            {props.children}
        </UsedCarListingContext.Provider>
    )
}

Car Details Component

export const UsedCarAdDetails = () => {
    const [usedCar, setUsedCar] = useContext(UsedCarListingContext)


    const changeHandler = (e) => {
        const {name, value} = e.target
        setUsedCar({
            ...usedCar,
            [name]: value
        })
    }
    const handleChange = ({target: {name, checked}}) => {
        setUsedCar({
            ...usedCar,
            [name]: checked
        })
    }

    

    return (
 
            <div className="container-1100 bg-white shadow-nav-bar w-full h-52 pt-12">
                <NavLink to={'/'} className='landing-nav-logo'>
                    <img
                        className='mr-20 mt-4 w-66 ottobay-logo-center'
                        src={OttobayGray}
                        alt={'logo'}
                    />
                </NavLink>
            </div>
            <div className="container-1050 mg-0auto flex  justify-between mt-48">
                <div className='container-700  p-20'>
                    <form>
                    
               
                    
                    <div className='ad-listing-input-wrapper mb-16-mobile mb-16 w-full-mobile flex items-center'>
                        <div className='ad-label-container'>
                            <label className="listing-input-label font-semibold mr-40"
                                   htmlFor="videoLink">History: </label>
                        </div>
                        <div className="ad-input-group-container">
                            <div className='checkbox-group-container'>
                                <CheckboxWithImage
                                    onChange={handleChange}
                                    name={'serviceHistory'}
                                    checked={usedCar.serviceHistory}
                                    label={'Service History'}
                                    icon={<GiAutoRepair/>}
                                    checkboxTitleClass={'historyCB'}
                                />
                                <CheckboxWithImage
                                    onChange={handleChange}
                                    name={'warranty'}
                                    checked={usedCar.warranty}
                                    label={'Warranty'}
                                    icon={<AiOutlineFileProtect/>}
                                    checkboxTitleClass={'historyCB'}
                                />
                            </div>
                        </div>
                    </div>
                    
                        <div>
                            <div className='checkbox-group-wrapper'>

                                {carFeatures.map(item => (
                                    <div className='feature-item'>
                                        <Checkbox
                                            label={item.name}
                                            onChange={handleFeaturesChange}
                                            checked={usedCar && usedCar.features.some(val => val === item.id)}
                                            value={item.id}
                                        />
                                    </div>
                                ))}
                            </div>
                        </div>
                        <div className="error-container"></div>
                    </div>
                    <div className="car-basic-submission-container">
                        <div> </div>
                        <button type='submit' className='search-button bg-button-primary text-white font-semibold rounded-4'> Next Step</button>
                    </div>
                    </form>
                </div>
    )
}

Advertisement

Answer

You seem to be calling a non existent function handleFeaturesChange in you feature-item checkbox.

Anyway, something like this should work:

const handleFeaturesChange = ({target: {value, checked}}) => {
    setUsedCar({
        ...usedCar,
        features: checked ? [
           ...usedCar.features,
           value, // add the value to previously selected features
        ] : usedCar.features.filter(val => val !== value) // remove the value 
   })
}

You could potentially replace the value with name string but then you’d need to update the condition in the checked param of the Checkbox to compare it with the name instead.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement