#reactjs #checkbox #react-hooks
Вопрос:
У меня возникла проблема с созданием списка флажков для правильной работы.
Я визуализирую свой флажок из массива объектов и отображаю его правильно. Когда я нажимаю на флажок, он отображается правильно, и если я затем нажимаю на другой, он работает нормально.
Проблема возникает, когда я устанавливаю флажок, а затем снова нажимаю на тот же самый. Даже если состояние меняется, оно не повторяется. Поэтому, когда я нажимаю на другой флажок, все повторяется, и предыдущий, который был нажат дважды, также обновляется.
Мой products.js файл:
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
Мой файл Forms.jsx (который отображается внутри App.js, и получает данные и наборы в качестве реквизитов — они не имеют отношения к делу, так как они не используются для флажка)
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 amp;amp; 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 amp;amp; state amp;amp; city amp;amp; 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={{label: state, key:'state-key'}}
options={states.map((state) => {
return {value: state, label: state}
})}
onChange={handleStateChange}
/>
{state amp;amp;
<div className="city-select">
<h4>Selecione a Cidade</h4>
<Select
name="form-city"
value={{label: city, key:'city-key'}}
options={sortedCities.map((item) => {
return {value: item.city, label: item.city}
})}
onChange={handleCityChange}
/>
</div> }
{state amp;amp; city amp;amp;
<div className="customer-select">
<h4>Selecione o Canal</h4>
<Select
name="form-customer"
value={{label: customer, key:'customer-key'}}
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
Я удалил URL-адрес, по которому размещаю данные, а также по-прежнему не отправляю данные флажка, потому что он не работает.
handleCheckboxChange-это имя функции, которая вызывается всякий раз, когда установлен флажок (onChange).
Это мой первый вопрос здесь, так что извините, если формат не самый лучший или требуется дополнительная информация.
Кто-нибудь может мне помочь? Заранее спасибо!
Ответ №1:
Мне любопытно посмотреть, сработает ли создание нового массива из текущего состояния. В настоящее время doing let checkboxList = productsState
является прямой ссылкой на состояние и не должен мутировать напрямую. У меня была похожая проблема с этим не так давно, React не выдает предупреждений о том, что вы напрямую изменяете состояние, и это приводит к странному поведению.
let checkboxList = [...productsState]
checkboxList.forEach(chkItem=>{
if(chkItem === product){
chkItem['checked'] = !chkItem['checked'];
}
})
Комментарии:
1. Спасибо за ответ, это действительно сработало. Я не думал, что меняю состояние напрямую, но ваш ответ имеет полный смысл. Спасибо за помощь 🙂