├── .idea ├── .gitignore ├── MIPT-1C-React-Course.iml ├── inspectionProfiles │ └── Project_Default.xml ├── modules.xml └── vcs.xml ├── README.md ├── additional ├── classes │ └── additional-class-01 │ │ ├── additional-class-01.pdf │ │ └── notes-add-01.md └── docs │ ├── exam-flow.md │ ├── homework-flow.md │ └── musthave-skills.md ├── classes ├── lecture-01 │ ├── notes-01.md │ ├── presentation-01.pdf │ └── resources │ │ ├── index.html │ │ └── styles.css ├── lecture-02 │ ├── notes-02.md │ ├── presentation-02.pdf │ └── resources │ │ └── index.js ├── lecture-03 │ ├── notes-03.md │ ├── presentation-03.pdf │ └── resources │ │ └── react-start │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── assets │ │ └── data.json │ │ ├── components │ │ ├── example-class │ │ │ ├── example-class.jsx │ │ │ └── example-class.module.css │ │ └── example │ │ │ ├── example.jsx │ │ │ └── example.module.css │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── reportWebVitals.js │ │ └── setupTests.js ├── lecture-04 │ ├── notes-04.md │ ├── presentation-04.pdf │ └── resources │ │ └── react-lifecycle │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ └── src │ │ ├── api │ │ └── mock-api.js │ │ ├── app │ │ ├── App.css │ │ └── App.js │ │ ├── assets │ │ └── data.json │ │ ├── components │ │ ├── clock │ │ │ ├── clock.jsx │ │ │ └── clock.module.css │ │ ├── custom-input │ │ │ ├── custom-input.jsx │ │ │ └── custom-input.module.css │ │ ├── data-changes │ │ │ ├── data-changes.jsx │ │ │ └── data-changes.module.css │ │ └── example-data │ │ │ ├── example-data.jsx │ │ │ └── example-data.module.css │ │ ├── index.css │ │ └── index.js ├── lecture-05 │ ├── notes-05.md │ ├── presentation-05.pdf │ └── resources │ │ └── react-styles-dive │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ └── src │ │ ├── app │ │ ├── App.css │ │ └── App.js │ │ ├── common │ │ └── styles │ │ │ ├── mixins.module.scss │ │ │ └── vars.module.scss │ │ ├── components │ │ ├── flex │ │ │ ├── flex.jsx │ │ │ └── flex.module.css │ │ ├── grid │ │ │ ├── grid.jsx │ │ │ └── grid.module.css │ │ ├── item │ │ │ ├── item.jsx │ │ │ └── item.module.scss │ │ └── list │ │ │ ├── list.jsx │ │ │ └── list.module.scss │ │ ├── index.css │ │ └── index.js ├── lecture-06 │ ├── notes-06.md │ └── presentation-06.pdf ├── lecture-07 │ ├── notes-07.md │ ├── presentation-07.pdf │ └── resources │ │ └── react-redux │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ └── src │ │ ├── api │ │ └── mock-api.js │ │ ├── app │ │ └── app.js │ │ ├── common │ │ ├── store │ │ │ ├── actions │ │ │ │ ├── changeData.js │ │ │ │ └── changeTheme.js │ │ │ ├── constants.js │ │ │ ├── model │ │ │ │ └── initialState.js │ │ │ └── reducers │ │ │ │ ├── data-reducers │ │ │ │ └── data-reducer.js │ │ │ │ ├── root-reducer.js │ │ │ │ └── theme-reducers │ │ │ │ └── theme-reducer.js │ │ └── styles │ │ │ └── vars.module.scss │ │ ├── components │ │ ├── item │ │ │ ├── item.jsx │ │ │ └── item.module.scss │ │ └── manager │ │ │ ├── manager.jsx │ │ │ └── manager.module.scss │ │ ├── index.css │ │ └── index.js ├── lecture-08 │ ├── notes-08.md │ ├── presentation-08.pdf │ └── resources │ │ └── react-router │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ └── src │ │ ├── app │ │ ├── app.jsx │ │ └── app.module.scss │ │ ├── common │ │ ├── components │ │ │ ├── content-holder │ │ │ │ ├── content-holder.jsx │ │ │ │ └── content-holder.module.scss │ │ │ ├── footer │ │ │ │ ├── footer.jsx │ │ │ │ └── footer.module.scss │ │ │ └── header │ │ │ │ ├── header.jsx │ │ │ │ └── header.module.scss │ │ ├── store │ │ │ ├── actions │ │ │ │ ├── changeData.js │ │ │ │ └── changeTheme.js │ │ │ ├── constants.js │ │ │ ├── middleware │ │ │ │ └── logger.js │ │ │ ├── model │ │ │ │ └── initialState.js │ │ │ └── reducers │ │ │ │ ├── data-reducers │ │ │ │ └── data-reducer.js │ │ │ │ ├── root-reducer.js │ │ │ │ └── theme-reducers │ │ │ │ └── theme-reducer.js │ │ └── styles │ │ │ └── vars.module.scss │ │ ├── components │ │ ├── item │ │ │ ├── item.jsx │ │ │ └── item.module.scss │ │ ├── items │ │ │ ├── items.jsx │ │ │ └── items.module.scss │ │ ├── layout │ │ │ └── layout.jsx │ │ └── manager │ │ │ ├── manager.jsx │ │ │ └── manager.module.scss │ │ ├── dev │ │ ├── data │ │ │ └── mocked-data.json │ │ └── utils │ │ │ └── mocked-data-provider.js │ │ ├── index.css │ │ ├── index.js │ │ └── pages │ │ ├── home.page.jsx │ │ ├── item.page.jsx │ │ ├── items.page.jsx │ │ └── manager.page.jsx ├── lecture-09 │ ├── notes-09.md │ ├── presentation-09.pdf │ └── resources │ │ └── react-hooks │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ └── src │ │ ├── App.css │ │ ├── App.js │ │ ├── index.css │ │ └── index.js ├── lecture-10 │ ├── notes-10.md │ ├── presentation-10.pdf │ └── resources │ │ └── react-custom-hook │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package-lock.json │ │ ├── package.json │ │ ├── public │ │ └── index.html │ │ └── src │ │ ├── app │ │ └── app.js │ │ ├── hooks │ │ └── use-local-storage.js │ │ ├── index.css │ │ └── index.js └── lecture-11 │ ├── notes-11.md │ ├── presentation-11.pdf │ └── resources │ └── stub.md └── homeworks ├── homework-01 ├── homework-01.md └── layout.png ├── homework-02 └── homework-02.md ├── homework-03 ├── homework-03.md └── mock-data.json ├── homework-04 ├── homework-04.md └── resources │ ├── data │ ├── articles.json │ └── comments.json │ ├── effects │ └── use-effect-usage.jsx │ └── helpers │ ├── get-articles.js │ └── get-comments-by-article.js ├── homework-05 └── homework-05.md ├── homework-06 └── homework-06.md ├── homework-07 └── homework-07.md ├── homework-08 └── homework-08.md ├── homework-09 └── homework-09.md ├── homework-10 └── homework-10.md └── homework-11 └── homework-11.md /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | -------------------------------------------------------------------------------- /.idea/MIPT-1C-React-Course.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Frontend разработка на ReactJS (курс не запущен в весеннем семестре 2025) 2 | 3 | 4 | ### О курсе 5 | 6 | Курс нацелен на получение базовых и продвинутых профессиональных компетенций 7 | в разработке фронтенда с помощью фреймворка ReactJS. 8 | 9 | 10 | ### Контакты преподавателя 11 | 12 | [Connections](https://github.com/JUSSIAR/JUSSIAR/blob/main/connection.md) 13 | 14 | 15 | ### Программа курса 16 | 17 | Данный раздел будет обновляться по мере течения курса. 18 | 19 | 1) Лекция 1: Вводная, HTML, CSS 20 | 2) Лекция 2: JS, NodeJS 21 | 3) Лекция 3: ReactJS 22 | 4) Лекция 4: React Lifecycle 23 | 5) Лекция 5: node-sass, classnames 24 | 6) Лекция 6: Advanced JS, ReactJS 25 | 7) Лекция 7: Redux 26 | 8) Лекция 8: React-router 27 | 9) Лекция 9: Async & Fetch 28 | 10) Лекция 10: Auth & Exploit 29 | 11) Лекция 11: Testing & CI stages 30 | 12) Лекция 12: Экзамен, заключительная 31 | 32 | 33 | ### Структура репозитория курса 34 | 35 | ```shell 36 | ├── README.md 37 | ├── additional 38 | │   ├── docs 39 | │   │   └── {some usefull docs} 40 | │   └── additional-class-{id} 41 | │   └── {optional some usefull material} 42 | ├── classes 43 | │   └── lecture-{id} 44 | │   ├── notes-{id}.md 45 | │   ├── presentation-{id}.pdf 46 | │   └── {optional files/resources} 47 | └── homeworks 48 | └── homework-{id} 49 | ├── homework-{id}.md 50 | └── {optional files/resources} 51 | ``` 52 | 53 | 54 | ### Формула оценки 55 | 56 | - Накопленная оценка будет равна среднему арифметическому за все ДЗ 57 | - За некоторые ДЗ будет возможность получить оценку из расчета больше 10 - будут доп баллы 58 | - Накопленная оценка по умолчанию является итоговой 59 | - При желании студента - есть возможность сдать экзамен, 60 | и в таком случае итоговая оценка будет считаться по формуле, 61 | указанной в разделе [информация об экзамене](#информация-об-экзамене) 62 | - Правила округления оценки: округляется только финальная оценка. 63 | Округление происходит по математическим правилам. 64 | В случае полуцелой оценки округление произойдет вверх в пользу студента. 65 | - Важным пунктом в формуле, в которой присутствуют элементы контроля с доп баллами является то, 66 | во что превратятся эти доп баллы. В нашей ситуации эти баллы имеют такую же ценность, как и обычные баллы. 67 | Но тогда возникает ситуация, что итоговая оценка может оказаться выше 10. 68 | Этого допустить нельзя)) 69 | Такую ситуацию разрешаем взятием в итоговой минимума из нее самой и 10 70 | (вне зависимости от решения по написанию экзамена). 71 | 72 | 73 | ### Табличка с оценками 74 | 75 | В таблице с оценками указано 11 домашек, из расчета, 76 | что у нас будет 12 занятий по плану и на всех занятиях кроме последнего 77 | будет выдано ДЗ. 78 | 79 | При возникновении форс-мажорных обстоятельств будем выходить из ситуации максимально лояльно 80 | и будут приниматься максимально легитимные решения. 81 | 82 | табличка отсутствует! 83 | 84 | ### Понижающие коэффициенты ДЗ 85 | 86 | - Все дедлайны планируются мягкими, 87 | то есть сдать домашку можно будет с опозданием, 88 | но в таком случае к оценке за дз будет применяться множитель - понижающий коэффициент. 89 | 90 | - Дедлайн на ДЗ будет выставляться в 1 неделю с момента завершения занятия. 91 | При сдаче до этого дедлайна понижающий коэффициент будет равен 1, 92 | то есть оценка будет без понижения. 93 | 94 | - Далее будет два мягких дедлайна: 95 | + 1 дедлайн: 2 недели с понижающим кофф. **0,5** 96 | + 2 дедлайн: позднее несгораемый понижающий коэф. **0,2** 97 | 98 | - **Важно**, что здесь указаны общие положения, 99 | но в домашку могут вноситься изменения по дедлайнам, при этом гарантируется, 100 | что изменения могут только увеличивать дедлайны и все решения такого рода принимаются 101 | в пользу студентов! 102 | 103 | ### Информация об экзамене 104 | 105 | Экзамен как элемент контроля на курсе не предполагается, 106 | но будет возможность сдать его по желанию. 107 | В случае принятия решения студентом о сдаче экзамена формула оценки меняется следующим образом: 108 | 109 | O_final = 0.7 * O_homework + 0.3 * O_exam 110 | 111 | **Здесь**: 112 | - O_final - итоговая оценка за курс 113 | - O_homework - средняя по дз 114 | - O_exam - оценка за экзамен 115 | 116 | [Подробнее об экзамене](./additional/docs/exam-flow.md) 117 | 118 | 119 | ### Информация по экстерну 120 | 121 | Закрытие курса экстерном позволяет получить объективную оценку ваших знаний по материалам курса 122 | без прохождения курса по общему флоу. 123 | 124 | Для того, чтобы закрыть курс экстерном необходимо написать мне **до 25-ого октября (25.10.2023) включительно** в [личку тг](https://t.me/jussiar). 125 | 126 | Есть два варианта: 127 | 128 | 1) показать и защитить мне готовый фронтовый проект на реакте, в котором нам необходимо провалидировать, 129 | что вы использовали достаточно технологий, чтобы оценить реальные навыки. 130 | 2) пройти со мной техническое интервью на ~1 час по вопросам экзамена, которые я буду просить раскрыть. 131 | 132 | 133 | ### Ссылки и благодарности 134 | 135 | Большое спасибо [Valery Statinov](https://github.com/ValeryStatinov) 136 | за предоставленные материалы! 137 | Некоторые составляющие и примеры этого курса заимствованы 138 | из аналогичного курса от [Valery Statinov](https://github.com/ValeryStatinov). 139 | -------------------------------------------------------------------------------- /additional/classes/additional-class-01/additional-class-01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/additional/classes/additional-class-01/additional-class-01.pdf -------------------------------------------------------------------------------- /additional/classes/additional-class-01/notes-add-01.md: -------------------------------------------------------------------------------- 1 | ## Доп занятие 1 2 | 3 | #### Поговорили про темы вокруг фронта и не только. 4 | 5 | #### План: 6 | 7 | 8 | 1) Построение и архитектурное разделение сущностей в приложении реакт 9 | 10 | 2) Server-side rendering 11 | 12 | 3) Опытах собесудований и тонкости 13 | 14 | 4) Идеи проектирования фронтенд систем и узкие места декомпозиции монолитов фронтенда 15 | 16 | 5) Дебаг и тесты 17 | 18 | 6) Инструментарий и архитектура для фуллстек разработки 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /additional/docs/exam-flow.md: -------------------------------------------------------------------------------- 1 | ### О том как проходит экзамен по курсу 2 | 3 | 4 | 1) Экзамен НЕ является обязательным на курсе 5 | 6 | 2) Экзамен содержит в себе только теоретическую часть 7 | 8 | 3) Формат экзамена - это короткое собеседование (~12-15 минут) 9 | 10 | 4) В процессе экзамена будет задано от 3 до 5 развернутых теоретических вопросов в зависимости от объема 11 | 12 | 5) Теоретическая выкладка курса содержится [тут](./musthave-skills.md), а также в файлах notes и презентациях 13 | 14 | 6) Для участия в экзамене необходимо записаться в [табличку](https://docs.google.com/spreadsheets/d/1GQsM9gNZwvTMWUDkq17c8EYSRbJLqJRUrEuM5w9MpLA/edit#gid=0) 15 | в удобный свободный слот 16 | 17 | 7) При отсутствии возможности попасть на экзамен в предложенные слоты, 18 | но наличии желания его писать - необходимо написать мне в [личку tg](https://t.me/JUSSIAR) 19 | 20 | 8) ВАЖНО: можно прийти на экзамен, сдать его, получить оценку, 21 | а после этого принять решение учитывать сдачу экзамена в итоговой оценке или нет. 22 | Рекомендуется пользоваться этой опцией при потенциальной необходимости зачета экзамена в оценку, 23 | либо при большом желании проверить свои знания! 24 | 25 | 9) Консультация будет проходить в формате онлайн в джитси по ссылке из внутренней таблицы в какой-то день, 26 | который мы придумаем в общем чате курса. 27 | 28 | 10) Всем успехов! 29 | -------------------------------------------------------------------------------- /additional/docs/homework-flow.md: -------------------------------------------------------------------------------- 1 | ## Pipeline сдачи домашки 2 | 3 | 1) Как только вы считаете, что дз готово - необходимо: 4 | 5 | - запушить ветку в ремоут 6 | - отребейзить ветку на хед мастера, чтобы при мерже коммиты шли подряд 7 | (хотя я при слиянии ваших ПР юзаю сквош, но тем не менее правильная практика - делать ребейз) 8 | - создать pull request на слияние данной ветки в мастер 9 | - внутри реквеста добавить меня в `assignees` 10 | - добавить меня еще в `reviewers` 11 | - Написать сообщение в потоке событий реквеста, что задание готово. 12 | 13 | 2) Итого для меня назначение `assign` и `review` + сообщение о готовности являются маркерами законченного дз, 14 | готового к проверке и время этих событий является временем сдачи дз. 15 | 16 | 3) В описании ПР указывайте номер ДЗ, к которому относится ПР 17 | 18 | 4) Одна домашка === один ПР 19 | 20 | 5) Проверка будет заключаться в добавлении комментариев к коду в вашем реквесте и выставлении оценки в комментарии 21 | 22 | 6) Как только все правки будут внесены, либо принято иное решение, я буду калибровать оценку и сливать ПР в мастер 23 | 24 | 7) Вы самостоятельно не сливаете ПР-ы с домашкой! 25 | 26 | 8) На внесение правок будет неделя с момента получение фидбэка по ПР 27 | -------------------------------------------------------------------------------- /additional/docs/musthave-skills.md: -------------------------------------------------------------------------------- 1 | ## Важно знать: 2 | 3 | 4 | ### HTML/СSS 5 | 6 | - DOM 7 | - че по роботам/сео 8 | - просто чекните первую презентацию/запись 9 | - сайзы в css, блочная модель и позиционирование 10 | 11 | 12 | ### JS 13 | 14 | - Иммутабельность примитивов в js 15 | - Стратегия копирования вложенных объектов и массивов 16 | - Работа и применение перебирающих методов массива 17 | - Строгое и нестрогое сравнение 18 | - JS однопоточный 19 | 20 | 21 | ### React 22 | 23 | - Способы движения данных между компонентами вверх и вниз 24 | - Работа жизненного цикла компонента 25 | - Что заставляет компонент пере-рендериться 26 | - setState асинхронный 27 | 28 | 29 | ### Lifecycle методы 30 | 31 | - методы при апдейте 32 | - методы при ре-рендеринге 33 | - методы при маунтинге 34 | 35 | 36 | ### CSS MODULES/SCSS 37 | 38 | - Модульные стили (file.module.css) и профит от их использования 39 | - Препроцессоры 40 | - Паттерн миксин 41 | - Переменные 42 | - nesting 43 | 44 | 45 | ### Redux 46 | 47 | - store init 48 | - централизация 49 | - actions 50 | - reducers/combiner 51 | - mappers 52 | - dispatch 53 | - data flow/observe 54 | 55 | 56 | ### Router 57 | 58 | - BrowserRouter 59 | - Route 60 | - Routes 61 | - index 62 | - Layout with Outlet 63 | - че зачем нам вообще этот роутер 64 | - useParams 65 | 66 | 67 | ### Hooks 68 | 69 | - useState 70 | - useEffect 71 | - useRef 72 | - useReducer 73 | - useMemo 74 | - useCallback 75 | - useContext 76 | - custom 77 | 78 | 79 | ### Async 80 | 81 | - механика промисов 82 | - resolve/reject 83 | - then/catch 84 | - async/await (optional) 85 | - event loop 86 | 87 | 88 | ### Api 89 | 90 | - fetch 91 | - Response 92 | - ok/status fields 93 | - blob() / json() / text() 94 | 95 | 96 | ### Auth 97 | 98 | - JWT 99 | - session cookie (Optional) 100 | 101 | 102 | ### Exploit 103 | 104 | - cookie 105 | - origins 106 | - CSRF 107 | - CORS 108 | 109 | 110 | ### Testing 111 | 112 | - виды/уровни 113 | - jest 114 | - describe 115 | - test/it 116 | - моки 117 | - окружение 118 | 119 | 120 | ### Browser/Node 121 | 122 | - setTimeout/clearTimeout 123 | - setInterval/clearInterval 124 | - window.localStorage 125 | - DI (Optional) 126 | -------------------------------------------------------------------------------- /classes/lecture-01/notes-01.md: -------------------------------------------------------------------------------- 1 | ## Вводная лекция 2 | 3 | 4 | #### Что успели: 5 | 6 | - Обсудили ход курса, оценку и экзамен 7 | - Поговорили о подходах static pages, AJAX, SPA, SSR 8 | - Поговорили о базовой структуре документа 9 | - Поговорили об основных тегах HTML 10 | - Поговорили о SEO оптимизирующих тегах для браузерных роботов 11 | - Затронули базовое поведение и классификацию селекторов CSS 12 | 13 | #### Что не успели: 14 | 15 | - Селекторы по атрибутам и их "операторы" успели только назвать 16 | - Подходы к верстке коллекций узлов DOM - flex и grid не успели 17 | - Не обсудили базовые CSS свойства 18 | - Не обсудили оптимизацию селекторов -------------------------------------------------------------------------------- /classes/lecture-01/presentation-01.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-01/presentation-01.pdf -------------------------------------------------------------------------------- /classes/lecture-01/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | title 6 | 7 | 8 | 9 |
10 |
child1
11 |
child1
12 |
child1
13 |
14 |
sub-child1 as child1
15 |
sub-child1
16 |
17 |
child1
18 |
19 | 20 | text 21 | 22 |
23 |

text

24 |

text

25 |

text

26 |

text

27 |

text

28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /classes/lecture-01/resources/styles.css: -------------------------------------------------------------------------------- 1 | .parent1 > .child1 { 2 | color: blue; 3 | } 4 | 5 | .parent1 .child1 { 6 | background-color: palevioletred; 7 | } 8 | 9 | .parent1 > .sub-child1 { 10 | background-color: peachpuff; 11 | } 12 | 13 | .child1 ~ .child1 { 14 | border-radius: 5px; 15 | } 16 | 17 | .child1, .sub-child1 { 18 | border: 2px solid black; 19 | } 20 | 21 | [href*='pp'] { 22 | color: blue; 23 | } 24 | 25 | .child1:first-child { 26 | text-decoration: underline; 27 | } 28 | 29 | .child1:first-child:hover { 30 | color: yellow; 31 | } 32 | 33 | .pseudo-examples { 34 | background-color: #a8a8a8; 35 | padding: 30px; 36 | } 37 | 38 | .item { 39 | margin-top: 10px; 40 | height: 40px; 41 | width: 200px; 42 | } 43 | 44 | .item:nth-child(even) { 45 | border: 1px solid gray; 46 | border-radius: 5px; 47 | } 48 | 49 | .item:not(:last-child) { 50 | color: red; 51 | } 52 | 53 | -------------------------------------------------------------------------------- /classes/lecture-02/notes-02.md: -------------------------------------------------------------------------------- 1 | ## Лекция 2: JS 2 | 3 | 4 | #### Что успели: 5 | 6 | - Определили примерные планы на рамки проекта на дистанцию курса 7 | - Успели все из презентации по JS 8 | - Успели рассмотреть то, что осталось с прошлого занятия 9 | 10 | #### Про проект: 11 | 12 | - Будем делать сервис для реализации действий с комментариями 13 | - Для работы с комментариями смоделируем список статей, 14 | на примере которых будем применять фронтовые хелперы 15 | - Обо всех инкрементах проекта далее в занятиях и в дз 16 | -------------------------------------------------------------------------------- /classes/lecture-02/presentation-02.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-02/presentation-02.pdf -------------------------------------------------------------------------------- /classes/lecture-02/resources/index.js: -------------------------------------------------------------------------------- 1 | const arr = [1, 3, 2, 4, 5, 14, 6] 2 | 3 | 4 | //map 5 | const mappedArr = arr.map((a, i) => a * i) 6 | //console.log(mappedArr) 7 | 8 | //filter 9 | const filteredArr = arr.filter(a => a % 2) 10 | // console.log(filteredArr) 11 | 12 | //reduce 13 | const reducedValue = arr.reduce((acc, item) => acc + item, 0) 14 | // console.log(reducedValue) 15 | 16 | //forEach 17 | arr.forEach(item => { 18 | // console.log(item % 3) 19 | }) 20 | 21 | //join 22 | //console.log(arr.join('--')) 23 | 24 | 25 | //console.log(arr.includes(33)) 26 | 27 | const arr1 = [ 28 | { 29 | name: 'x', 30 | age: 10 31 | }, 32 | { 33 | name: 'y', 34 | age: 20 35 | }, 36 | { 37 | name: 'a', 38 | age: 33 39 | }, 40 | { 41 | name: 'b', 42 | age: -4 43 | } 44 | ] 45 | 46 | // console.log(arr1.sort((a, b) => { 47 | // if (a.name === b.name) { 48 | // return 0 49 | // } 50 | // return a.name > b.name ? 1 : -1 51 | // })) 52 | 53 | // console.table(arr1) 54 | 55 | // console.group('group') 56 | // 57 | // console.log(1) 58 | // console.log(2) 59 | // 60 | // console.groupEnd() 61 | // 62 | // console.log(3) 63 | 64 | 65 | -------------------------------------------------------------------------------- /classes/lecture-03/notes-03.md: -------------------------------------------------------------------------------- 1 | ## Лекция 3: ReactJS 2 | 3 | 4 | #### Что успели: 5 | 6 | - Обсудили идеологию реакта 7 | - Проговорили базовую структуру проекта реакт 8 | - Обсудили основные сущности в разработке на реакте 9 | - Разобрали классовый и функциональный подход 10 | - Верхнеуровнево затронули методы и процессы жизненного цикла 11 | - Реализовали две версии задачи `counter` 12 | - Реализовали data mapping 13 | -------------------------------------------------------------------------------- /classes/lecture-03/presentation-03.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-03/presentation-03.pdf -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/README.md: -------------------------------------------------------------------------------- 1 | # React-start-practice -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-start", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-03/resources/react-start/public/favicon.ico -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-03/resources/react-start/public/logo192.png -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-03/resources/react-start/public/logo512.png -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | .cont { 41 | display: flex; 42 | justify-content: center; 43 | } 44 | 45 | .button { 46 | width: 50px; 47 | height: 30px; 48 | font-size: 16px; 49 | border: 1px solid black; 50 | border-radius: 5px; 51 | } 52 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/App.js: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | 3 | // Components import 4 | import {ExampleClass} from "./components/example-class/example-class"; 5 | import {Example} from "./components/example/example"; 6 | 7 | // Hook import for state 8 | import React, {useState} from "react"; 9 | 10 | /** 11 | * General component 12 | * @returns {JSX.Element} 13 | * @constructor 14 | */ 15 | function App() { 16 | // State usage for counter task with functional component 17 | const [counter, setCounter] = useState(22) 18 | 19 | const inc = () => { 20 | setCounter(oldCounter => oldCounter + 1) 21 | } 22 | 23 | const dec = () => { 24 | setCounter(oldCounter => oldCounter - 1) 25 | } 26 | 27 | const arr = [1, 2, 3, 4, 5] 28 | 29 | return ( 30 |
31 | 32 |
33 | {arr.map(item => )} 34 |
35 | 36 |

Functional component counter task

37 |
{counter}
38 |
39 |
+
40 |
41 |
42 |
-
43 |
44 |
45 | ); 46 | } 47 | 48 | export default App; 49 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/assets/data.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": "data", 3 | "name": "name" 4 | } -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/components/example-class/example-class.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | /** 4 | * Class Component example 5 | * Counter task 6 | */ 7 | export class ExampleClass extends React.Component { 8 | 9 | state = { 10 | counter: 0 11 | } 12 | 13 | inc = () => { 14 | this.setState(oldState => ({ 15 | counter: oldState.counter + 1 16 | })) 17 | } 18 | 19 | dec = () => { 20 | this.setState(oldState => ({ 21 | counter: oldState.counter - 1 22 | })) 23 | } 24 | 25 | render() { 26 | return ( 27 | <> 28 |

Class component

29 |
{this.state.counter}
30 |
31 |
+
32 |
33 |
34 |
-
35 |
36 | 37 | ) 38 | } 39 | } -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/components/example-class/example-class.module.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-03/resources/react-start/src/components/example-class/example-class.module.css -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/components/example/example.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | // JSON Data import model-changes 4 | import data from '../../assets/data.json' 5 | 6 | // Imports CSS module as JS object 7 | import s from './example.module.css' 8 | 9 | // Simple helper 10 | const pow2 = x => x * x 11 | 12 | /** 13 | * Functional Component model-changes 14 | * Power 2 task 15 | * @see props object decomposition 16 | */ 17 | export function Example({value}) { 18 | // Making content string 19 | const content = `Value = ${value}; Value ^ 2 = ${pow2(value)}` 20 | 21 | return ( 22 | <> 23 |

Pow2

24 |
  • 25 | {content} 26 |
  • 27 | 28 | ) 29 | } 30 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/components/example/example.module.css: -------------------------------------------------------------------------------- 1 | .block { 2 | color: gray; 3 | } 4 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | const root = ReactDOM.createRoot(document.getElementById('root')); 8 | root.render( 9 | 10 | 11 | 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for model-changes: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /classes/lecture-03/resources/react-start/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /classes/lecture-04/notes-04.md: -------------------------------------------------------------------------------- 1 | ## Лекция 4: ReactJS Lifecycle 2 | 3 | 4 | #### Что затронули: 5 | 6 | - сверху-вниз: props 7 | - снизу-вверх: callback 8 | - методы жизненного цикла 9 | - процессы жизненного цикла 10 | - работа с данными 11 | - прикладные задачи 12 | 13 | 14 | #### Что не затронули: 15 | 16 | - аналогичные механики для функций на хуках(проговорили только мемо, но тоже поверхностно) 17 | -------------------------------------------------------------------------------- /classes/lecture-04/presentation-04.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-04/presentation-04.pdf -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/README.md: -------------------------------------------------------------------------------- 1 | # React-lifecycle-practice -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-lifecycle", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "react": "^18.2.0", 10 | "react-dom": "^18.2.0", 11 | "react-scripts": "5.0.1", 12 | "web-vitals": "^2.1.4" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/api/mock-api.js: -------------------------------------------------------------------------------- 1 | import dataset from '../assets/data.json' 2 | 3 | const DURATION = 1000; 4 | 5 | export async function getData() { 6 | return new Promise(resolve => { 7 | setTimeout(() => resolve(dataset), DURATION) 8 | }) 9 | } -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/app/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | .cont { 41 | display: flex; 42 | justify-content: center; 43 | } 44 | 45 | .button { 46 | width: 50px; 47 | height: 30px; 48 | font-size: 16px; 49 | border: 1px solid black; 50 | border-radius: 5px; 51 | } 52 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/app/App.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import './App.css'; 4 | 5 | import data from '../assets/data.json' 6 | 7 | import {Clock} from "../components/clock/clock"; 8 | import {ExampleData} from "../components/example-data/example-data"; 9 | import {DataChanges} from "../components/data-changes/data-changes"; 10 | 11 | function App() { 12 | return ( 13 |
    14 | 15 | 16 | 17 |
    18 | ); 19 | } 20 | 21 | export default App; 22 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/assets/data.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "text": "Text 1", 4 | "color": "red" 5 | }, 6 | { 7 | "text": "Text 2", 8 | "color": "green" 9 | }, 10 | { 11 | "text": "Text 3", 12 | "color": "yellow" 13 | }, 14 | { 15 | "text": "Text 4", 16 | "color": "orange" 17 | }, 18 | { 19 | "text": "Text 5", 20 | "color": "purple" 21 | } 22 | ] -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/clock/clock.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import s from './clock.module.css' 4 | 5 | const DateTimeComponent = ({ date }) => ( 6 |
    7 | {date.toLocaleTimeString()} 8 |
    9 | ) 10 | 11 | export class Clock extends React.Component { 12 | state = { 13 | time: new Date() 14 | } 15 | interval = null 16 | 17 | componentDidMount() { 18 | this.interval = setInterval(() => { 19 | this.setState({ time: new Date() }) 20 | }, 1000) 21 | } 22 | 23 | componentWillUnmount() { 24 | clearInterval(this.interval) 25 | } 26 | 27 | render() { 28 | return ( 29 |
    30 |
    Current time:
    31 | 32 |
    33 | ) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/clock/clock.module.css: -------------------------------------------------------------------------------- 1 | .clocks { 2 | font-size: 48px; 3 | font-weight: bold; 4 | } 5 | 6 | .title { 7 | font-size: 54px; 8 | } -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/custom-input/custom-input.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import s from './custom-input.module.css' 4 | 5 | export const CustomInput = ({data, onChange}) => ( 6 | 12 | ) -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/custom-input/custom-input.module.css: -------------------------------------------------------------------------------- 1 | .custom { 2 | border: 3px solid gray; 3 | border-radius: 4px; 4 | } -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/data-changes/data-changes.jsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react' 2 | import {CustomInput} from "../custom-input/custom-input"; 3 | 4 | export function DataChanges() { 5 | const [arr, setArr] = useState([]) 6 | const [line, setLine] = useState('') 7 | 8 | const onChange = event => { 9 | const { value } = event.target 10 | setLine(value) 11 | } 12 | 13 | const pushLine = () => { 14 | setArr([...arr, line]) 15 | } 16 | 17 | return ( 18 | <> 19 |

    Data changes

    20 |
    21 | {`[${arr.join(', ')}]`} 22 |
    23 | 27 | 30 | 31 | ) 32 | } 33 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/data-changes/data-changes.module.css: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/example-data/example-data.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import {getData} from "../../api/mock-api"; 4 | 5 | import s from './example-data.module.css' 6 | 7 | 8 | export class ExampleData extends React.Component { 9 | 10 | state = { 11 | data: Array.from( 12 | {length: this.props.dataSize}, 13 | () => ({}) 14 | ) 15 | } 16 | 17 | componentDidMount() { 18 | getData().then(dataset => { 19 | this.setState(() => ({ 20 | data: [...dataset] 21 | })) 22 | }) 23 | } 24 | 25 | render() { 26 | return ( 27 |
    28 | {this.state.data.map(({text, color}, id) => ( 29 |
    30 | {text || 'Loading...'} 31 |
    32 | ))} 33 |
    34 | ) 35 | } 36 | 37 | 38 | } -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/components/example-data/example-data.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | border-radius: 20px; 3 | 4 | margin: 30px auto; 5 | padding: 30px; 6 | width: 260px; 7 | background-color: #606060; 8 | } 9 | 10 | .item { 11 | border-radius: 10px; 12 | 13 | height: 50px; 14 | 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | 19 | background-color: #dddddd; 20 | margin: 20px 0 0; 21 | } -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /classes/lecture-04/resources/react-lifecycle/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './app/App'; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById('root')); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /classes/lecture-05/notes-05.md: -------------------------------------------------------------------------------- 1 | ## Лекция 5: Deep dive CSS. 2 | 3 | 4 | #### Что затронули: 5 | 6 | - flexbox 7 | - grid 8 | - препроцессоры scss/sass 9 | - css modules 10 | - scss vars 11 | - scss mixins 12 | - nesting 13 | - conditional styles 14 | - classnames 15 | 16 | 17 | #### Что не затронули: 18 | 19 | - media-запросы оставлены на самостоятельное изучение 20 | -------------------------------------------------------------------------------- /classes/lecture-05/presentation-05.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-05/presentation-05.pdf -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/README.md: -------------------------------------------------------------------------------- 1 | # React-styles-dive-practice -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-styles-dive", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "classnames": "^2.3.2", 10 | "node-sass": "^7.0.3", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-scripts": "5.0.1", 14 | "web-vitals": "^2.1.4" 15 | }, 16 | "scripts": { 17 | "start": "react-scripts start", 18 | "build": "react-scripts build", 19 | "test": "react-scripts test", 20 | "eject": "react-scripts eject" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/app/App.css: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/app/App.js: -------------------------------------------------------------------------------- 1 | import React, {useState} from "react"; 2 | 3 | import './App.css'; 4 | 5 | import {List} from "../components/list/list"; 6 | import {Grid} from "../components/grid/grid"; 7 | import {Flex} from "../components/flex/flex"; 8 | 9 | function App() { 10 | const [themeFlag, setThemeFlag] = useState(false) 11 | 12 | const listener = () => { 13 | setThemeFlag(!themeFlag) 14 | } 15 | 16 | const theme = themeFlag ? 'dark' : 'light' 17 | 18 | return ( 19 |
    20 | 21 | 22 | 23 | 24 |
    25 | ); 26 | } 27 | 28 | export default App; 29 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/common/styles/mixins.module.scss: -------------------------------------------------------------------------------- 1 | @mixin fontSettings($size: 20) { 2 | font-weight: bold; 3 | font-size: $size; 4 | } 5 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/common/styles/vars.module.scss: -------------------------------------------------------------------------------- 1 | $lightPrimaryColor: rgb(214, 214, 214); 2 | $lightSecondaryColor: rgb(0, 38, 100); 3 | 4 | $darkPrimaryColor: rgb(0, 0, 0); 5 | $darkSecondaryColor: rgb(138, 90, 0); 6 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/flex/flex.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import s from './flex.module.css' 4 | 5 | export function Flex() { 6 | return ( 7 |
    8 |
    t1
    9 |
    t2
    10 |
    11 | ) 12 | } 13 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/flex/flex.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | /*flex-direction: column-reverse;*/ 4 | justify-content: space-around; 5 | align-items: center; 6 | flex-wrap: wrap; 7 | 8 | margin: 30px; 9 | padding: 10px; 10 | 11 | border: 1px solid black; 12 | border-radius: 10px; 13 | background-color: silver; 14 | 15 | /*width: 1000px;*/ 16 | /*height: 100px;*/ 17 | } 18 | 19 | .item1, 20 | .item2 { 21 | min-width: 200px; 22 | height: 30px; 23 | 24 | border: 1px solid black; 25 | border-radius: 5px; 26 | background-color: white; 27 | } 28 | 29 | .item1 { 30 | flex: 1; 31 | } 32 | 33 | .item2 { 34 | flex: 1; 35 | } 36 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/grid/grid.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import s from './grid.module.css' 4 | 5 | export function Grid() { 6 | return ( 7 |
    8 |
    9 |
    10 |
    11 |
    12 |
    13 | ) 14 | } -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/grid/grid.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: grid; 3 | grid-gap: 5px; 4 | grid-template-columns: 1fr 2fr; 5 | grid-template-rows: 1fr 1fr; 6 | 7 | margin: 30px; 8 | padding: 10px; 9 | 10 | border: 1px solid black; 11 | border-radius: 10px; 12 | background-color: silver; 13 | } 14 | 15 | 16 | .item { 17 | width: 50px; 18 | height: 30px; 19 | 20 | border: 1px solid black; 21 | border-radius: 5px; 22 | background-color: white; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/item/item.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classnames from 'classnames/bind' 3 | 4 | import s from './item.module.scss' 5 | 6 | const cn = classnames.bind(s) 7 | 8 | export function Item({text, theme}) { 9 | return ( 10 |
    11 |
    12 | {text} 13 |
    14 |
    15 | ) 16 | } 17 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/item/item.module.scss: -------------------------------------------------------------------------------- 1 | @import "../../common/styles/vars.module.scss"; 2 | @import "../../common/styles/mixins.module.scss"; 3 | 4 | .item { 5 | width: 50px; 6 | height: 30px; 7 | border-radius: 10px; 8 | 9 | &-light { 10 | background-color: $lightSecondaryColor; 11 | } 12 | 13 | &-dark { 14 | background-color: $darkSecondaryColor; 15 | } 16 | } 17 | 18 | .text { 19 | @include fontSettings(32); 20 | 21 | &-light { 22 | color: $lightPrimaryColor; 23 | } 24 | 25 | &-dark { 26 | color: $darkPrimaryColor; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/list/list.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classnames from 'classnames/bind' 3 | 4 | import {Item} from '../item/item' 5 | 6 | import s from './list.module.scss' 7 | 8 | const cn = classnames.bind(s) 9 | 10 | export function List({theme}) { 11 | 12 | const arr = [] 13 | for (let i = 0; i < 5; i++) { 14 | arr.push(`text-${i}`) 15 | } 16 | 17 | return ( 18 |
    19 | {arr.map(text => )} 20 |
    21 | ) 22 | } -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/components/list/list.module.scss: -------------------------------------------------------------------------------- 1 | @import "../../common/styles/vars.module.scss"; 2 | 3 | .list { 4 | display: flex; 5 | justify-content: space-around; 6 | flex-direction: column; 7 | align-items: center; 8 | 9 | height: 500px; 10 | width: 200px; 11 | 12 | border-radius: 20px; 13 | margin: 30px; 14 | 15 | &-light { 16 | background-color: $lightPrimaryColor; 17 | } 18 | 19 | &-dark { 20 | background-color: $darkPrimaryColor; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /classes/lecture-05/resources/react-styles-dive/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom/client'; 3 | import './index.css'; 4 | import App from './app/App'; 5 | 6 | const root = ReactDOM.createRoot(document.getElementById('root')); 7 | root.render( 8 | 9 | 10 | 11 | ); 12 | -------------------------------------------------------------------------------- /classes/lecture-06/notes-06.md: -------------------------------------------------------------------------------- 1 | ## Лекция 6: Advanced JS, ReactJS. 2 | 3 | 4 | #### Что затронули: 5 | 6 | - React Virtual DOM 7 | - diff-алгоритм (поверхностно) и его эвристики 8 | - var VS const/let (поверхностно) 9 | - JS call-stack 10 | - JS callback queue 11 | - Async flow 12 | - Event Loop(поверхностно) 13 | - Изоляция работы с макро и микро тасками в WebAPI(NodeAPI) 14 | - Кейсы работы с контекстом в JS 15 | 16 | 17 | #### Полезное: 18 | 19 | - Неплохая статья в переводе для понимания concurrency в js: 20 | 21 | https://developer.mozilla.org/ru/docs/Web/JavaScript/EventLoop 22 | -------------------------------------------------------------------------------- /classes/lecture-06/presentation-06.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-06/presentation-06.pdf -------------------------------------------------------------------------------- /classes/lecture-07/notes-07.md: -------------------------------------------------------------------------------- 1 | ## Лекция 7: Redux. 2 | 3 | 4 | #### Что обсудили: 5 | 6 | - проблема перемещения данных по путям в дереве компонентов 7 | - проблема non-pure functions при работе со стейтом 8 | - идея redux 9 | - redux + react-redux 10 | - flux arch, observer 11 | - redux model: view -> action -> reducer -> store -> view 12 | - идея структурного разделения файлов под управлением redux в проекте 13 | - подход и необходимость подключения redux, централизация store 14 | 15 | 16 | #### Что не разобрали, но затронем далее: 17 | 18 | - добавление middleware при подключении redux-store к проекту 19 | - проблема асинхронных вызовов в redux 20 | - решение redux-thunk 21 | - middleware для разработки + кастомный логгер 22 | -------------------------------------------------------------------------------- /classes/lecture-07/presentation-07.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-07/presentation-07.pdf -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/README.md: -------------------------------------------------------------------------------- 1 | # React-redux-practice -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-redux", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "classnames": "^2.3.2", 10 | "node-sass": "^7.0.3", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-redux": "^7.2.2", 14 | "react-scripts": "5.0.1", 15 | "redux": "^4.0.5", 16 | "web-vitals": "^2.1.4" 17 | }, 18 | "scripts": { 19 | "start": "react-scripts start", 20 | "build": "react-scripts build", 21 | "test": "react-scripts test", 22 | "eject": "react-scripts eject" 23 | }, 24 | "eslintConfig": { 25 | "extends": [ 26 | "react-app", 27 | "react-app/jest" 28 | ] 29 | }, 30 | "browserslist": { 31 | "production": [ 32 | ">0.2%", 33 | "not dead", 34 | "not op_mini all" 35 | ], 36 | "development": [ 37 | "last 1 chrome version", 38 | "last 1 firefox version", 39 | "last 1 safari version" 40 | ] 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/api/mock-api.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-07/resources/react-redux/src/api/mock-api.js -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/app/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { createStore } from 'redux' 3 | import { Provider } from 'react-redux' 4 | 5 | import Item from '../components/item/item.jsx' 6 | import Manager from '../components/manager/manager.jsx' 7 | 8 | import { rootReducer } from '../common/store/reducers/root-reducer.js' 9 | 10 | const store = createStore(rootReducer) 11 | 12 | function App() { 13 | return ( 14 | 15 |
    16 | 17 | 18 |
    19 |
    20 | ) 21 | } 22 | 23 | export default App; 24 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/actions/changeData.js: -------------------------------------------------------------------------------- 1 | import { ActionTypes } from '../constants' 2 | 3 | export const actionChangeData = (data) => ({ 4 | type: ActionTypes.changeData, 5 | payload: data 6 | }) -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/actions/changeTheme.js: -------------------------------------------------------------------------------- 1 | import { ActionTypes } from '../constants' 2 | 3 | export const actionChangeTheme = () => ({ 4 | type: ActionTypes.changeTheme 5 | }) -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/constants.js: -------------------------------------------------------------------------------- 1 | export const ActionTypes = { 2 | changeTheme: 'CHANGE_THEME', 3 | changeData: 'CHANGE_DATA', 4 | } 5 | 6 | export const ThemeTypes = { 7 | light: 'light', 8 | dark: 'dark', 9 | } 10 | 11 | export const defaultTheme = ThemeTypes.light 12 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/model/initialState.js: -------------------------------------------------------------------------------- 1 | import { defaultTheme } from '../constants' 2 | 3 | export const initialState = () => ({ 4 | theme: defaultTheme, 5 | data: '', 6 | }) -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/reducers/data-reducers/data-reducer.js: -------------------------------------------------------------------------------- 1 | import { initialState } from '../../model/initialState' 2 | import { ActionTypes } from '../../constants' 3 | 4 | export const dataReducer = (state = initialState(), action) => { 5 | switch (action.type) { 6 | case ActionTypes.changeData: { 7 | return { 8 | ...state, 9 | data: action.payload, 10 | } 11 | } 12 | default: { 13 | return state 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/reducers/root-reducer.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import { themeReducer } from './theme-reducers/theme-reducer.js' 3 | import { dataReducer } from './data-reducers/data-reducer.js' 4 | 5 | export const rootReducer = combineReducers({ 6 | themeReducer, 7 | dataReducer, 8 | }) 9 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/store/reducers/theme-reducers/theme-reducer.js: -------------------------------------------------------------------------------- 1 | import { initialState } from '../../model/initialState' 2 | import { ActionTypes, ThemeTypes } from '../../constants' 3 | 4 | export const themeReducer = (state = initialState(), action) => { 5 | switch (action.type) { 6 | case ActionTypes.changeTheme: { 7 | const newTheme = state.theme === ThemeTypes.light 8 | ? ThemeTypes.dark 9 | : ThemeTypes.light 10 | 11 | return { 12 | ...state, 13 | theme: newTheme, 14 | } 15 | } 16 | default: { 17 | return state 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/common/styles/vars.module.scss: -------------------------------------------------------------------------------- 1 | $lightPrimaryColor: rgb(214, 214, 214); 2 | $lightSecondaryColor: rgb(0, 38, 100); 3 | 4 | $darkPrimaryColor: rgb(0, 0, 0); 5 | $darkSecondaryColor: rgb(138, 90, 0); 6 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/components/item/item.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classnames from 'classnames/bind' 3 | import { connect } from 'react-router' 4 | 5 | import s from './item.module.scss' 6 | 7 | const cn = classnames.bind(s) 8 | 9 | const mapStateToProps = (state) => ({ 10 | theme: state.themeReducer.theme, 11 | data: state.dataReducer.data, 12 | }) 13 | 14 | function Item({data, theme}) { 15 | return ( 16 |
    17 |
    18 | {data} 19 |
    20 |
    21 | ) 22 | } 23 | 24 | export default connect(mapStateToProps)(Item) 25 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/components/item/item.module.scss: -------------------------------------------------------------------------------- 1 | @import "../../common/styles/vars.module.scss"; 2 | 3 | .item { 4 | width: 250px; 5 | height: 30px; 6 | border-radius: 10px; 7 | 8 | &-light { 9 | background-color: $lightSecondaryColor; 10 | } 11 | 12 | &-dark { 13 | background-color: $darkSecondaryColor; 14 | } 15 | } 16 | 17 | .text { 18 | &-light { 19 | color: $lightPrimaryColor; 20 | } 21 | 22 | &-dark { 23 | color: $darkPrimaryColor; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/components/manager/manager.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classnames from 'classnames/bind' 3 | import { connect } from 'react-router' 4 | 5 | import { actionChangeTheme } from '../../common/store/actions/changeTheme.js' 6 | import { actionChangeData } from '../../common/store/actions/changeData.js' 7 | 8 | import s from './manager.module.scss' 9 | import {ThemeTypes} from "../../common/store/constants"; 10 | 11 | const cn = classnames.bind(s) 12 | 13 | const mapStateToProps = (state) => ({ 14 | theme: state.themeReducer.theme, 15 | data: state.dataReducer.data, 16 | }) 17 | 18 | const mapDispatchToProps = (dispatch) => ({ 19 | changeData: (data) => dispatch(actionChangeData(data)), 20 | changeTheme: () => dispatch(actionChangeTheme()), 21 | }) 22 | 23 | function Manager({theme, data, changeData, changeTheme}) { 24 | const dataHandler = event => { 25 | const { value } = event.target 26 | changeData(value) 27 | } 28 | 29 | const themeHandler = () => { 30 | changeTheme() 31 | } 32 | 33 | return ( 34 |
    35 | 40 | 46 |
    47 | ) 48 | } 49 | 50 | export default connect(mapStateToProps, mapDispatchToProps)(Manager) 51 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/components/manager/manager.module.scss: -------------------------------------------------------------------------------- 1 | @import "../../common/styles/vars.module.scss"; 2 | 3 | .manager { 4 | width: 250px; 5 | height: 30px; 6 | border-radius: 10px; 7 | 8 | &-light { 9 | background-color: $lightSecondaryColor; 10 | } 11 | 12 | &-dark { 13 | background-color: $darkSecondaryColor; 14 | } 15 | } 16 | 17 | .text { 18 | &-light { 19 | color: $lightPrimaryColor; 20 | } 21 | 22 | &-dark { 23 | color: $darkPrimaryColor; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /classes/lecture-07/resources/react-redux/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom/client' 3 | import './index.css' 4 | import App from './app/app' 5 | 6 | const root = ReactDOM.createRoot(document.getElementById('root')) 7 | root.render( 8 | 9 | 10 | 11 | ) 12 | -------------------------------------------------------------------------------- /classes/lecture-08/notes-08.md: -------------------------------------------------------------------------------- 1 | ## Лекция 8: Router. 2 | 3 | #### Что затронули: 4 | 5 | - поговорили про маршрутизацию 6 | - разобрали инструмент реализации SPA роутинга 7 | - посмотрели на работу в старой версии `react-router-dom@v5` на теоретических примерах 8 | - разобрали новую версию пакета `react-router-dom@v6` на практике 9 | 10 | #### Можно глянуть: 11 | 12 | - Usage старой версии на примере моего старого учебного проекта: 13 | 14 | + https://github.com/JUSSIAR/ReactJS-ToDoList-Project/blob/main/project1/src/components/mainComp/mainComp.js#L39-L54 15 | + https://github.com/JUSSIAR/ReactJS-ToDoList-Project/blob/main/project1/src/components/project/project.js#L58 16 | + https://github.com/JUSSIAR/ReactJS-ToDoList-Project/blob/main/project1/src/components/project/project.js#L134 17 | 18 | P.S.: Проект сделан очень плохо, но как историческая выкладка применения 19 | старых версий библиотек - довольно забавный легаси пример)) 20 | 21 | - Неплохой плейлист на ютубе для быстрого погружения в роутер v6: 22 | 23 | + https://youtube.com/playlist?list=PLiZoB8JBsdznY1XwBcBhHL9L7S_shPGVE 24 | 25 | - Чуть ресурсов для парсинга и валидаци параметров url: 26 | 27 | + https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/isNaN 28 | + https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/parseInt 29 | + https://developer.mozilla.org/ru/docs/Web/JavaScript/Reference/Global_Objects/RegExp 30 | -------------------------------------------------------------------------------- /classes/lecture-08/presentation-08.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JUSSIAR/MIPT-1C-React-Course/2b314a59695cd3b94992cc04ab19dcc3970ab1ba/classes/lecture-08/presentation-08.pdf -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/README.md: -------------------------------------------------------------------------------- 1 | # React-router-practice -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-router", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.16.5", 7 | "@testing-library/react": "^13.4.0", 8 | "@testing-library/user-event": "^13.5.0", 9 | "classnames": "^2.3.2", 10 | "node-sass": "^7.0.3", 11 | "react": "^18.2.0", 12 | "react-dom": "^18.2.0", 13 | "react-redux": "^7.2.2", 14 | "react-router-dom": "^6.4.2", 15 | "react-scripts": "5.0.1", 16 | "redux": "^4.0.5", 17 | "redux-thunk": "^2.4.1", 18 | "web-vitals": "^2.1.4" 19 | }, 20 | "scripts": { 21 | "start": "react-scripts start", 22 | "build": "react-scripts build", 23 | "test": "react-scripts test", 24 | "eject": "react-scripts eject" 25 | }, 26 | "eslintConfig": { 27 | "extends": [ 28 | "react-app", 29 | "react-app/jest" 30 | ] 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React App 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/app/app.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { applyMiddleware, createStore } from 'redux' 3 | import { Provider } from 'react-redux' 4 | import { Routes, Route, Navigate } from 'react-router-dom' 5 | 6 | import { rootReducer } from '../common/store/reducers/root-reducer' 7 | import { actionFireLogger } from '../common/store/middleware/logger' 8 | 9 | import Layout from '../components/layout/layout' 10 | import HomePage from '../pages/home.page' 11 | import ItemPage from '../pages/item.page' 12 | import ItemsPage from '../pages/items.page' 13 | import ManagerPage from '../pages/manager.page' 14 | 15 | import styles from './app.module.scss' 16 | 17 | const store = createStore(rootReducer, applyMiddleware(actionFireLogger)) 18 | 19 | function App() { 20 | return ( 21 | 22 |
    23 | 24 | }> 25 | }/> 26 | }/> 27 | }/> 28 | }/> 29 | }/> 30 | 31 | 32 |
    33 |
    34 | ) 35 | } 36 | 37 | export default App; 38 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/app/app.module.scss: -------------------------------------------------------------------------------- 1 | .applicationHolder { 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | padding: 0; 6 | border: none; 7 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/components/content-holder/content-holder.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import styles from './content-holder.module.scss' 4 | 5 | const ContentHolder = ({children}) => ( 6 |
    7 | {children} 8 |
    9 | ) 10 | 11 | export default ContentHolder -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/components/content-holder/content-holder.module.scss: -------------------------------------------------------------------------------- 1 | .contentHolder { 2 | min-height: 77vh; 3 | margin: 0; 4 | padding: 4vh; 5 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/components/footer/footer.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | import styles from './footer.module.scss' 4 | 5 | const Footer = () => ( 6 |
    7 | Подвал приложения 8 |
    9 | ) 10 | 11 | export default Footer -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/components/footer/footer.module.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | width: 100%; 3 | height: 7vh; 4 | text-align: center; 5 | 6 | margin: 0; 7 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/components/header/header.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {Link} from 'react-router-dom' 3 | 4 | import styles from './header.module.scss' 5 | 6 | const Header = () => ( 7 |
    8 |

    9 | Шапка с навигацией 10 |

    11 | 16 |
    17 | ) 18 | 19 | export default Header -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/components/header/header.module.scss: -------------------------------------------------------------------------------- 1 | .header { 2 | display: flex; 3 | align-items: center; 4 | justify-content: space-between; 5 | 6 | height: 8vh; 7 | 8 | padding: 0 50px; 9 | margin: 0; 10 | 11 | background-color: #dddddd; 12 | } 13 | 14 | .title { 15 | font-size: 24px; 16 | font-weight: bold; 17 | } 18 | 19 | .navigation { 20 | display: flex; 21 | align-items: center; 22 | justify-content: space-around; 23 | 24 | width: 40%; 25 | height: 100%; 26 | 27 | font-size: 22px; 28 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/actions/changeData.js: -------------------------------------------------------------------------------- 1 | import { ActionTypes } from '../constants' 2 | 3 | export const actionChangeData = (data) => ({ 4 | type: ActionTypes.changeData, 5 | payload: data 6 | }) -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/actions/changeTheme.js: -------------------------------------------------------------------------------- 1 | import { ActionTypes } from '../constants' 2 | 3 | export const actionChangeTheme = () => ({ 4 | type: ActionTypes.changeTheme 5 | }) -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/constants.js: -------------------------------------------------------------------------------- 1 | export const ActionTypes = { 2 | changeTheme: 'CHANGE_THEME', 3 | changeData: 'CHANGE_DATA', 4 | } 5 | 6 | export const ThemeTypes = { 7 | light: 'light', 8 | dark: 'dark', 9 | } 10 | 11 | export const defaultTheme = ThemeTypes.light 12 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/middleware/logger.js: -------------------------------------------------------------------------------- 1 | export const actionFireLogger = ({}) => (next) => (action) => { 2 | console.log(`action [${action.type}] was fired with payload: ${action.payload}`) 3 | return next(action) 4 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/model/initialState.js: -------------------------------------------------------------------------------- 1 | import { defaultTheme } from '../constants' 2 | 3 | export const initialState = () => ({ 4 | theme: defaultTheme, 5 | data: '', 6 | }) -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/reducers/data-reducers/data-reducer.js: -------------------------------------------------------------------------------- 1 | import { initialState } from '../../model/initialState' 2 | import { ActionTypes } from '../../constants' 3 | 4 | export const dataReducer = (state = initialState(), action) => { 5 | switch (action.type) { 6 | case ActionTypes.changeData: { 7 | return { 8 | ...state, 9 | data: action.payload, 10 | } 11 | } 12 | default: { 13 | return state 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/reducers/root-reducer.js: -------------------------------------------------------------------------------- 1 | import { combineReducers } from 'redux' 2 | import { themeReducer } from './theme-reducers/theme-reducer.js' 3 | import { dataReducer } from './data-reducers/data-reducer.js' 4 | 5 | export const rootReducer = combineReducers({ 6 | themeReducer, 7 | dataReducer, 8 | }) 9 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/store/reducers/theme-reducers/theme-reducer.js: -------------------------------------------------------------------------------- 1 | import { initialState } from '../../model/initialState' 2 | import { ActionTypes, ThemeTypes } from '../../constants' 3 | 4 | export const themeReducer = (state = initialState(), action) => { 5 | switch (action.type) { 6 | case ActionTypes.changeTheme: { 7 | const newTheme = state.theme === ThemeTypes.light 8 | ? ThemeTypes.dark 9 | : ThemeTypes.light 10 | 11 | return { 12 | ...state, 13 | theme: newTheme, 14 | } 15 | } 16 | default: { 17 | return state 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/common/styles/vars.module.scss: -------------------------------------------------------------------------------- 1 | $lightPrimaryColor: rgb(214, 214, 214); 2 | $lightSecondaryColor: rgb(0, 38, 100); 3 | 4 | $darkPrimaryColor: rgb(0, 0, 0); 5 | $darkSecondaryColor: rgb(138, 90, 0); 6 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/components/item/item.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import classnames from 'classnames/bind' 3 | import { connect } from 'react-redux' 4 | import { useParams } from 'react-router-dom' 5 | 6 | import { mockedDataProvider } from '../../dev/utils/mocked-data-provider' 7 | 8 | import s from './item.module.scss' 9 | 10 | const cn = classnames.bind(s) 11 | 12 | const mapStateToProps = (state) => ({ 13 | theme: state.themeReducer.theme, 14 | data: state.dataReducer.data, 15 | }) 16 | 17 | function Item({data, theme}) { 18 | const { id } = useParams() 19 | 20 | const { title, text } = mockedDataProvider(id, data) 21 | 22 | return ( 23 |
    24 |
    25 |

    {title}

    26 |

    {text}

    27 |
    28 |
    29 | ) 30 | } 31 | 32 | export default connect(mapStateToProps)(Item) 33 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/components/item/item.module.scss: -------------------------------------------------------------------------------- 1 | @import "../../common/styles/vars.module.scss"; 2 | 3 | .item { 4 | width: 300px; 5 | height: 100px; 6 | border-radius: 10px; 7 | 8 | &-light { 9 | background-color: $lightSecondaryColor; 10 | } 11 | 12 | &-dark { 13 | background-color: $darkSecondaryColor; 14 | } 15 | } 16 | 17 | .text { 18 | &-light { 19 | color: $lightPrimaryColor; 20 | } 21 | 22 | &-dark { 23 | color: $darkPrimaryColor; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/components/items/items.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {Link} from 'react-router-dom' 3 | 4 | import styles from './items.module.scss' 5 | 6 | const items = [ 7 | { 8 | id: 1, 9 | text: "a" 10 | }, 11 | { 12 | id: 2, 13 | text: "bb" 14 | }, 15 | { 16 | id: 3, 17 | text: "ccc" 18 | } 19 | ] 20 | 21 | function Items() { 22 | return ( 23 |
    24 | {items.map(({id, text}) => ( 25 | 26 | {text} 27 | 28 | ))} 29 |
    30 | ) 31 | } 32 | 33 | export default Items 34 | -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/components/items/items.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: space-around; 5 | 6 | height: 20vh; 7 | width: 100%; 8 | } 9 | 10 | .link { 11 | display: inline-flex; 12 | align-items: center; 13 | justify-content: center; 14 | 15 | height: 35px; 16 | width: 400px; 17 | 18 | font-size: 22px; 19 | text-decoration: none; 20 | 21 | color: #282c34; 22 | background-color: #a8a8a8; 23 | 24 | border-radius: 10px; 25 | } 26 | 27 | @media (hover: hover) { 28 | .link:hover { 29 | background-color: #d9d9d9; 30 | } 31 | } -------------------------------------------------------------------------------- /classes/lecture-08/resources/react-router/src/components/layout/layout.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import {Outlet} from 'react-router-dom' 3 | 4 | import Header from '../../common/components/header/header' 5 | import Footer from '../../common/components/footer/footer' 6 | import ContentHolder from '../../common/components/content-holder/content-holder' 7 | 8 | function Layout() { 9 | return ( 10 | <> 11 |
    12 | 13 | 14 | 15 |