仅当Switch初始为选中状态时,首次点击无法切换状态
React Switch组件初始选中时首次点击无响应问题修复
问题根源
你的问题核心在于状态拆分维护+非受控组件混合写法导致的状态不同步:
- 单独维护
switchVal和product两个状态,初始switchVal为undefined,当产品feat初始为true时,两者未同步初始化,第一次点击时状态更新逻辑冲突。 - Switch组件使用
defaultChecked(非受控写法),同时又试图用switchVal控制状态,这种混合写法让React无法正确追踪组件状态。 - 用
useEffect同步switchVal到product属于冗余操作,还会因闭包问题导致状态更新不及时。
修复步骤 & 完整代码
核心修改点
- 删除单独的
switchVal状态,直接复用product.feat统一管理Switch状态 - 将Switch改为受控组件,用
checked={product.feat}替代defaultChecked - 修改输入处理逻辑,让Switch复用统一的
changeHandler,去掉冗余的同步useEffect - 所有输入组件从
defaultValue改为value,统一使用受控组件写法
import { useEffect, useState } from "react"; import { useNavigate, useParams } from "react-router-dom"; import getOneProduct from "../../../Services/getOneProduct"; import { useProductsDispatch } from "../../../Context/productsContext"; import { toast } from "react-toastify"; function EditProductForm() { const dispatch = useProductsDispatch(); const redirect = useNavigate(); const [product, setProduct] = useState({ name: '', desc: '', price: '', offPrice: '', image: '', feat: null, uid: '', date: '', }); // 统一处理所有输入,自动适配复选框和普通输入 const changeHandler = (e) => { const value = e.target.type === 'checkbox' ? e.target.checked : e.target.value; setProduct(prev => ({ ...prev, [e.target.name]: value, })); }; const editProductSubmit = (e) => { e.preventDefault(); dispatch({ type: 'EDIT_PRODUCT', payload: { productId, product } }); redirect("/admin/dashboard"); }; const { id: productId } = useParams(); useEffect(() => { const fetchedProduct = async () => { try { const { data } = await getOneProduct(productId); setProduct({ name: data.name, desc: data.desc, price: data.price, offPrice: data.offPrice, image: data.image, feat: data.feat, uid: data.uid, date: data.date, }); } catch (error) { console.log(error); } }; fetchedProduct(); }, [productId]); return ( <div> <form className="add-product-form" onSubmit={editProductSubmit}> <div className="form-floating mb-3"> <input value={product.name} onChange={changeHandler} type="text" className="form-control" id="productName" name="name" placeholder="نام محصول" /> <label className="form-label" htmlFor="productName">نام محصول</label> </div> <div className="form-floating mb-3"> <textarea value={product.desc} onChange={changeHandler} className="form-control" id="productDesc" name="desc" placeholder="Leave a comment here" style={{ height: 200 }} /> <label htmlFor="productDesc">توضیحات محصول</label> </div> <div className="form-floating mb-3"> <input value={product.price} onChange={changeHandler} type="number" className="form-control" id="productPrice" name="price" placeholder="قیمت اصلی محصول" /> <label className="form-label" htmlFor="productPrice">قیمت اصلی محصول</label> </div> <div className="form-floating mb-3"> <input value={product.offPrice} onChange={changeHandler} type="number" className="form-control" id="productOffPrice" name="offPrice" placeholder="قیمت با تخفیف محصول" /> <label className="form-label" htmlFor="productOffPrice">قیمت با تخفیف محصول</label> </div> <div className="form-floating mb-3"> <input value={product.image} onChange={changeHandler} type="text" className="form-control" id="productImage" name="image" placeholder="لینک تصویر محصول" /> <label className="form-label" htmlFor="productImage">لینک تصویر محصول</label> </div> {/* 修复后的Switch组件 */} <div className="form-check form-switch form-check-reverse mb-3"> <input onChange={changeHandler} checked={product.feat} type="checkbox" className="form-check-input" id="productFeat" name="feat" role="switch" /> <label className="form-check-label" htmlFor="productFeat">محصول ویژه است</label> </div> <div className="mb-3"> <button type="submit" className="btn btn-success">ویرایش محصول</button> </div> </form> </div> ); } export default EditProductForm;
额外说明
统一使用受控组件写法后,所有表单状态都集中在product对象中,避免了多状态同步的问题;同时复用changeHandler减少了代码冗余,让逻辑更清晰。
内容的提问来源于stack exchange,提问作者Mansour Sarhani
相关产品推荐
相关产品推荐

