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!