Реагировать на изменение значения объекта TS

У меня есть объект 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 ... Как мне заставить это работать, так как бренд технически является строкой, поэтому он не работает, как мне установить/снять флажки в правильных полях, спасибо

Отвечает ли это на ваш вопрос? Невозможно динамически отображать компонент через Object.entries

ghybs 13.04.2023 04:19
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
0
1
54
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Ваш объект на самом деле не подходит для 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 . Что я делаю не так? Спасибо

Mat 13.04.2023 04:36

ааа, вам нужно изменить тип Shoes, brand: Brand на brand: Array<Brand> , пожалуйста, посмотрите упрощенную версию реализации codeandbox.io/s/black-grass-qi557m?file=/src/App.tsx

Someone Special 13.04.2023 14:50

У вас есть синтаксическая ошибка в вашем 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>
)

Игровая площадка ТС

Другие вопросы по теме