Conversation
| "skipLibCheck": true, | ||
| "esModuleInterop": true, | ||
| "allowSyntheticDefaultImports": true, | ||
| "strict": false, |
There was a problem hiding this comment.
Добавил tsconfig.json, что бы вручную настроить некоторые правила (а то что-то и мпортом было, зачем-то от нас требовали указывать расширение файла)
Можешь переключить в "strict": true,, что б получить супер-жёсткий typescript))
| "resolveJsonModule": true, | ||
| "isolatedModules": true, | ||
| "noEmit": true, | ||
| "jsx": "react-jsx" |
There was a problem hiding this comment.
Вот эта штука ("jsx": "react-jsx") фиксит проблему импорта, когда почему-то от нас требуют указывать расширение файла:
import { Search } from '../search-component/search-component.tsx';
Причина в JSX-разметке в импортируемом модуле
| ItemsCount.defaultProps = { | ||
| itemsCount: 0, | ||
| }; |
There was a problem hiding this comment.
Тут пример исопльзования значений попросов по-умолчанию
| genre: string; | ||
| } | ||
|
|
||
| const moviesData: ReadonlyArray<Readonly<Movie>> = [ |
There was a problem hiding this comment.
Таким образом moviesData типизировать в текущих условиях не обязательно, просто хотел похвастаться системой типов в typescript. ReadonlyArray запретит менять ссылки в массиве (т.е. присвивать элементу другой объект), а Readonly запретит менять поля эленмента Movie
| const moviesData: ReadonlyArray<Readonly<Movie>> = [ | ||
| { | ||
| id: 1, | ||
| id: '00000000-0000-0000-0000-000000000001', |
There was a problem hiding this comment.
На сколько я помню, API для этого менторинга имеет ввиду GUID для идентифкатора фильма. Ссылку на API можно найти где-то в pdf с заданием. Там есть Swagger, можно посмотреть чо да как работает
| type GenreType = 'ALL' | 'DOCUMENTARY' | 'COMEDY' | 'HORROR' | 'CRIME'; | ||
|
|
||
| interface Genre { | ||
| readonly name: GenreType; | ||
| isActive: boolean; | ||
| } | ||
|
|
||
| let genresData: Array<Genre> = [ | ||
| { name: 'ALL', isActive: true }, | ||
| { name: 'DOCUMENTARY', isActive: false }, | ||
| { name: 'COMEDY', isActive: false }, |
There was a problem hiding this comment.
Опять необязательный вариант типизации структуры для жанра. Такая схема позволит контролировать, что в идентификатор жанра не засунули что-то кроме 'ALL', 'DOCUMENTARY' и проч.
А вот это readonly name: GenreType; позволит задвать жанр только при инициализации экземпляра, мутировать после уже нельзя
| <a | ||
| href="#" | ||
| className={genre.isActive ? 'genres-navigation_active' : ''} | ||
| className={bem('genre', { active: genre.isActive })} |
There was a problem hiding this comment.
Вот тут пример работы с модификаторами по BEM-методологии
| .genres-navigation { | ||
| width: 25%; | ||
|
|
||
| ul { | ||
| display: flex; | ||
| list-style-type: none; | ||
| } | ||
|
|
||
| li { | ||
| flex: auto; | ||
| } | ||
|
|
||
| &__tab:hover { | ||
| cursor: pointer; | ||
| } | ||
|
|
||
| &__tab:visited { | ||
| color: gray; | ||
| } | ||
|
|
||
| &__genre { | ||
| color: white; | ||
|
|
||
| &--active { | ||
| border-bottom: 4px #f65261 solid; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Чем хорош SASS - например, что можно вкладывать селекторы один в другой, чтобы не утонуть в куче стилей элементов блока. SASS - это пре-процессор сителей, который умеет в переменные, импорты стилей из других модулей со стилями и много чего еще.
| .item-counter { | ||
| &__label { | ||
| font-size: 20px; | ||
| } | ||
|
|
||
| &__label_number { | ||
| font-weight: bolder; | ||
| } | ||
| } |
There was a problem hiding this comment.
Еще пример вложения стилей
| interface MovieItemProps { | ||
| movieName: string; | ||
| movieGenre: string; | ||
| movieYear: number; | ||
| imgPath: string; |
There was a problem hiding this comment.
В typescript тип (type) - это как бы интерфесы на анаболиках. Можно типизировать сигнатуру функции, или даже сделать именованый тип для базового: type GenreType = string. Или для определенигя кортежа: type Data = [number, string];. Для пропсов же чаще используют интерфейсы. Интерфейсы обычно использутся, если нужно только лишь определить "форму" объекта: набор полей и функций
| function MovieItem({ movieName, movieGenre, movieYear, imgPath }: ItemProps) { | ||
| const MovieItem: React.FC<MovieItemProps> = props => { |
There was a problem hiding this comment.
Тут ты использовал деструктивное присваивание пропсов:
{ movieName, movieGenre, movieYear, imgPath }: ItemProps
На текущем этапе это ок, но когда компонент разростается и у него появляется свое состояние, то деструктивное присваивание будет скорее мешать, т.к. с ходу не разберешь откуда пришли данные - то ли из пропсов, то ли определы прямо в компоненте. Поэтому props.movieName предпочительние
| placeholder="What do you want to watch?" | ||
| className={props.className} | ||
| id="search-input" | ||
| ></input> | ||
| className={classNames(bem(), props.className)} |
There was a problem hiding this comment.
Тут типичное решение типичной задачи - комбинирование собственного имени класса с проксируемым откуда-то сверху (из родительсокго компонента)
No description provided.