У меня есть объект 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
, вы можете использовать базовые карты и фильтры
привет, я начинаю реализовывать это таким образом, спасибо, но при этом я получаю сообщение об ошибке: Type '{ brand: string; проверено: ложь; В }[]" отсутствуют следующие свойства типа "Бренд": brand, checked . Что я делаю не так? Спасибо
ааа, вам нужно изменить тип Shoes, brand: Brand на brand: Array<Brand> , пожалуйста, посмотрите упрощенную версию реализации codeandbox.io/s/black-grass-qi557m?file=/src/App.tsx
У вас есть синтаксическая ошибка в вашем 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>
)
Отвечает ли это на ваш вопрос? Невозможно динамически отображать компонент через Object.entries