Home > Blockchain >  Unable to handle multiple input type checkbox fields in React
Unable to handle multiple input type checkbox fields in React

Time:10-08

So I have this component where I have around 15 input type checkboxes, which upon checked/unchecked show/hide images. All fields have an onChange handler which takes the category name of the images. The category type is then checked in a conditional and calls another helper function. All of them follows the same steps.

Now I'm trying to attach a local state to each of the checkboxes(all 15 of them) so that when one of them is checked it will show the respective category image and when unchecked it will hide the image.

Right now it is working but in reverse. I mean when it is checked it hides the image and shows it when unchecked. Also, on the first click on the checkbox, there is no response (no hide or show).

Here's the component. For simplicity's sake I'm only showing 3 fields. But there are around 15:

const Images= () => {

    const [ isNatureChecked, setIsNatureChecked ]       = useState( false );
    const [ isCityChecked, setIsCityChecked ]           = useState( false );
    const [ isAbstractChecked, setIsAbstractChecked ]   = useState( false );


    const handleImages = ( e, type ) => {

          if ( type === 'nature' ) {

                setIsNatureChecked( !isNatureChecked );
                showImage( 0, isNatureChecked && new Image.Nature() );

          } else if ( type === 'city' ) {

                setIsCityChecked( !isCityChecked );
                showImage( 1, isCityChecked && new Image.City() );

          } else if ( type === 'abstract' ) {
                
                setIsAbstractChecked( !isAbstractChecked);
                showImage( 2, isAbstractChecked && new Image.Abstract() );

          } 

     }

     return (
           <div>
                 <input type="checkbox" checked={isNatureChecked} onChange={( e ) => handleImages( e, 'nature' )} />
                 <input type="checkbox" checked={isCityChecked} onClick={( e ) => handleImages( e, 'city' )} />
                 <input type="checkbox" checked={isAbstractChecked} onClick={( e ) => handleImages( e, 'abstract' )} />
           </div>
      )
}

The first parameter in showImage func is the index.

How can I make the checkbox work in the right way? I mean when it will be checked, it will show image, and when it will be unchecked it will hide it.

Moreover, please suggest if this code can be refactored. 15 input fields will have 15 states and 15 conditionals. That's too many repetitive code which I want to avoid. So please suggest me the correct way.

CodePudding user response:

your handleImages function doesn't have an updated value which is why you don't see a change on the first click. You need to use the useEffect hook to dynamically show image and set the state value as a dependency.

A better way to approach this would be to create an object state e.g.

const [checkedImages, setCheckedImages] = useState({ nature: false, city: false, abstract: false });

and then your handler can switch the boolean states without any if else conditions.

    const handleChange = (e, type) => {
  setCheckedImages(prevState => ({...prevState, [type]: !checkedImages[type]}))
}

you will need a useEffect block to dynamically show images

lastly, the input fields can be mapped without having to write them one by one

CodePudding user response:

Try This

    const Images= () => {
        const [imagesArr,setImagesArr] = useState([{name:'Nature',isChecked:false,index:0},{name:'City',isChecked:false,index:1},{name:'Substract',isChecked:false,index:2},])
        const handleImages = ( e, imageData,imageDataIndex ) => {
    
                    setImagesArr(arr=>{
                       arr[imageDataIndex] = {...arr[imageDataIndex],isChecked:e.target.checked}
                       return arr
                    });
                    showImage( imageData.index, e.target.checked && new Image[imageData.name]() );
    
         }
    
         return (
               <div>
                     {
                       imageData && imageData.length && 
                       imageData.map((data,index)=>{
                       return (
                         <input type="checkbox" checked={data.isChecked} onChange={( e ) => handleImages( e, data,index )} />
                       )
                       }
                     }
                     
               </div>
          )
    }
  • Related