我有一个useState对象:
const [filterState,setFilterState] = useState({
Brands:{
NewBalance: false,
Nike: false,
Addiddas: false,
Converse:false,
UnderArmour:false,
},
Gender:{
Male: false,
Female: false,
Kids:false,
}
});
,我将每个品牌呈现为如下的复选框:
{
Object.entries(filterState.Brands).map(([brand, checked])=>
<div className="" key={brand} >
<label htmlFor={brand} className="mr-[10px]">{brand}: </label>
<input type="checkbox" name={brand} className="cursor-pointer" checked={checked}
onChange={()=>setFilterState({Brands:{...filterState.Brands,Nike:!checked},Gender:
{...filterState.Gender}})}/>
</div>
)}
如果你看一下onChange,这就是我的问题所在:
onChange={()=>setFilterState({Brands{...filterState.Brands,Nike:!checked},Gender{...filterState.Gender}})}/>
,如果我给它一个确切的键,如Nike
,那么我没有问题,但这只改变了一个复选框。如果我将Nike
更改为brand
,那么我得到一个错误:'brand' does not exist in type ...
我如何使此工作作为品牌在技术上是一个字符串,所以它不起作用,我如何使它选中/取消选中正确的框,谢谢
您的对象不是真正的TS友好,尝试更改为以下对象样式:
const [filterState,setFilterState] = useState<Shoes>({
brand:[{
brand: "NewBalance",
checked: false,
},
{
brand: "Nike",
checked: false,
},
......
],
gender: [{
}]
})
然后你可以像
那样声明你的类型type Brand = {
brand: string;
checked: boolean;
}
type Gender = {
gender: "Male" | "Female" | "Kid";
checked: boolean;
}
type Shoes = {
gender: Array<Gender>;
brand: Array<Brand>;
}
那么你不再需要使用Object.entries
,你可以使用基本的映射和过滤器
codesandbox
你的onChange有一个语法错误。应该是:
onChange={()=>setFilterState({Brands:{...filterState.Brands,Nike:!checked},Gender:{...filterState.Gender}})}/>
更清晰一点,那就是:
onChange={() => setFilterState({
Brands: { ...filterState.Brands, Nike: !checked },
Gender: {...filterState.Gender }
})}/>
可以改进Object.entries
的类型。
// an alias that has a better typing than the original.
const entries: <T extends object>(o: T) => ({ [K in keyof T]: [K, T[K]] }[keyof T])[] = Object.entries;
const [filterState, setFilterState] = useState({
Brands: {
NewBalance: false,
Nike: false,
Addiddas: false,
Converse: false,
UnderArmour: false,
},
Gender: {
Male: false,
Female: false,
Kids: false,
}
});
entries(filterState.Brands).map(([brand, checked]) =>
<div className="" key={brand} >
<label htmlFor={brand} className="mr-[10px]">{brand}: </label>
<input type="checkbox" name={brand} className="cursor-pointer" checked={checked}
onChange={() => setFilterState(prev => ({ ...prev, Brands: { ...prev.Brands, [brand]: !checked } }))} />
</div>
)
TS操场