首页 > 解决方案 > 当我在同一个项目中单击两次时,为什么我的复选框不呈现?

问题描述

我在使复选框列表正常工作时遇到问题。

我正在从一组对象中渲染我的复选框,并正确显示它。当我单击一个复选框时,它会正确呈现,如果我然后单击另一个复选框,它会正常工作。

当我单击一个复选框,然后再次单击同一个复选框时,就会出现此问题。即使状态发生变化,它也不会重新渲染。因此,当我单击另一个复选框时,所有内容都会重新呈现,并且前一个被单击两次的复选框也会更新。

我的 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 中呈现,并接收数据和 setThanks 作为道具 - 这些不相关,因为它们不用于复选框)

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={{label: state, key:'state-key'}}
                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={{label: city, key:'city-key'}}
                    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={{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)。

这是我在这里的第一个问题,如果格式不是最好的或需要更多信息,很抱歉。

有人可以帮我吗?提前致谢!

标签: reactjscheckboxreact-hooks

解决方案


我很想知道从当前状态创建一个新数组是否可行。目前,doinglet checkboxList = productsState是对状态的直接引用,不应直接改变。不久前我有一个类似的问题,React 没有警告你正在直接改变状态,它会导致奇怪的行为。

let checkboxList = [...productsState]

checkboxList.forEach(chkItem=>{
    if(chkItem === product){
        chkItem['checked'] = !chkItem['checked'];
    }
})

推荐阅读