mardi 28 septembre 2021

React - My checkbox box are not rendering when I click twice in the same item

I'm having an issue to set make a checkbox list to work properly.

I'm rendering my checkbox from a an array of objects, and displaying it properly. When I click on a checkbox, it renders properly, and if I then click in another one, it works fine.

The issue happens when I click in a checkbox, and then again click on the same one. Even though the state changes, it doesn't rerender. So When I click on another checkbox, everything rerenders, and the previous one that was clicked twice is also updated.

My products.js file:

const products = [
    {name: "CZ15B29XTD", img: "", checked: false},
    {name: "CZ16B17IPRO", img: "", checked: false},
    {name: "CZ26B47I2X", img: "", checked: false},
    {name: "CZ36B96I2X", img: "", checked: false},
    {name: "CZ37B39I2X", img: "", checked: false},
    {name: "CZ37B60IPRO", img: "", checked: false},
    {name: "CZ48B18IPRO", img: "", checked: false},
    {name: "CZ58B23I2X", img: "", checked: false},
    {name: "2607XTD", img: "", checked: false},
]

export default products

My Forms.jsx file (that is rendered inside the App.js, and receives data and setThanks as props - these are not relevant, as they are not used for the checkbox)

import React, { useState } from 'react'
import Select from 'react-select'
import axios from 'axios'
import products from '../products'

function Form({ data, setThanks }) {
    // Configure states
    const [state, setState] = useState('')
    const [city, setCity] = useState('')
    const [customer, setCustomer] = useState('')
    const [name, setName] = useState('')
    const [email, setEmail] = useState('')
    const [errMessage, setErrMessage] = useState(null)
    const [productsState, setProductsState] = useState(products)
    const [selectedValue, setSelectedValue] = useState(null);

    // Configure options
    let statesArr = []
    let citiesArr = []
    let customersArr = []

    // Populate the stateArr with all the possible states
    data.forEach(item => {
        statesArr.push(item.state)
        citiesArr.push(item.city)
        customersArr.push(item.customer)
    })
    // Remove duplicates
    const states = [...new Set(statesArr)].sort()

    const filteredCities = data.filter(item => item.state === state)
    // Add all cities to the citiesArr
    citiesArr = filteredCities.map(function(obj){
        return obj.city;
    })
    // Remove duplicates and sort
    const singleCities = filteredCities.filter(function (el, i, arr) {
        return citiesArr.indexOf(el.city) === i;
    });
    const sortedCities = singleCities.sort((a, b) => a.city < b.city? -1 : 1)

    
    const filteredCustomers = data.filter(item => item.state === state && item.city === city)
    // Add all cities to the customersArr
    customersArr = filteredCustomers.map(function(obj){
        return obj.city;
    })
    // Remove duplicates and sort
    const singlesCustomer = filteredCustomers.filter(function (el, i, arr) {
        return customersArr.indexOf(el.city) === i;
    });
    const sortedCustomers = singlesCustomer.sort((a, b) => a.city < b.city? -1 : 1)


    // HANDLER functions
    // ***********************************

    const handleStateChange = (e) => {
        setState(e.value)
        setCity(null)
        setCustomer(null)
    }

    const handleCityChange = (e) => {
        setCity(e.value)
        setCustomer(null)
    }

    const handleCustomerChange = (e) => {
        setCustomer(e.value)
    }

    const handleChangeName = e => {
        setName(e.target.value)
    }

    const handleChangeEmail = e => {
        setEmail(e.target.value)
    }

    const handleCheckboxChange = (e, product) => {
        setSelectedValue(e.target.value)

        let checkboxList = productsState
        checkboxList.forEach(chkItem=>{
            if(chkItem === product){
              chkItem['checked'] = !chkItem['checked'];
            }
        })
        setProductsState(checkboxList)
        console.log(productsState)
    }

    console.log(selectedValue)

    const handleSubmit = e => {
        e.preventDefault()

        if(name && state && city && customer) {
            axios.post('removed',{
                "data": {
                    "Nome": name, 
                    "Email": email, 
                    "Estado": state, 
                    "Cidade": city, 
                    "Distribuidor": customer,
                    "Email Sent": "false",
                    "Customer Email Sent": "false"
                }
            }).then( response => {
                console.log(response.data);
                setThanks(true)
            });
        }
        else {
            setErrMessage('Por favor preencher todos os campos acima')
        }
        
    }

    // Log all the values
    console.log(state, city, customer, name, email)

    return (
        <div className="form-container">
            <h4>Nome Completo</h4>
            <input type="text" id="client-name" name="client-name" placeholder="Digite seu nome" onChange={handleChangeName} required/>
            
            <h4>Email</h4>
            <input type="text" id="client-email" name="client-email" placeholder="Digite seu email" onChange={handleChangeEmail} required/>
            
            <h4>Selecione o Estado</h4>
            <Select 
                name="form-name"
                value=
                options={states.map((state) => {
                    return {value: state, label: state}
                })} 
                onChange={handleStateChange}
                />

            {state && 
            <div className="city-select">
                <h4>Selecione a Cidade</h4>
                <Select
                    name="form-city" 
                    value=
                    options={sortedCities.map((item) => {
                        return {value: item.city, label: item.city}
                    })} 
                    onChange={handleCityChange}
                    /> 
            </div> }

            {state && city &&
            <div className="customer-select">
                <h4>Selecione o Canal</h4>
                <Select 
                    name="form-customer"
                    value=
                    options={sortedCustomers.map((item) => {
                        return {value: item.customer, label: item.customer}
                    })} 
                    onChange={handleCustomerChange}    
                    />
            </div> }
            
            <h4>Selecione os Produtos</h4>
            {productsState.map(product => {
                return (
                <div key={product.name}>    
                    <input type="checkbox" 
                        id={product.name} 
                        name={product.name} 
                        value={product.name} 
                        checked={product.checked}
                        onChange={(e) => handleCheckboxChange(e, product)}
                        />
                    <label htmlFor={product.name}> {product.name}</label><br/>
                </div>
            )})}

            <button onClick={handleSubmit}> Enviar </button>
            <h4 className="error-message">{errMessage}</h4>
        </div>
    )
}

export default Form

I've removed the url that I'm posting the data, and also I'm still not sending the checkbox data, because it's not working.

handleCheckboxChange is the name of the function that is called whenever a checkbox is select (onChange).

It's my first question here, so sorry if the format is not the best or some more information is needed.

Could someone help me out? Thanks in advance!




Aucun commentaire:

Enregistrer un commentaire