├── .gitattributes ├── 9781484266953.jpg ├── Ch1 ├── .DS_Store ├── TS-getting-started.ts └── index.html ├── Ch10 ├── .DS_Store └── e2e_ts_testing_with_puppeteer │ ├── .env │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ └── README │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ └── tsconfig.json ├── Ch12 ├── .env ├── .eslintignore ├── .eslintrc ├── .gitignore ├── .prettierrc ├── README.md ├── README_CRA.md ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js ├── generate-react-cli.json ├── jest-puppeteer.config.js ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── README │ │ └── ScrollToTop │ │ │ └── ScrollToTop.tsx │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ ├── MyPage │ │ │ ├── MyPage.scss │ │ │ ├── MyPage.test.tsx │ │ │ ├── MyPage.tsx │ │ │ └── math.tsx │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx └── tsconfig.json ├── Ch2 ├── .DS_Store ├── hello-cra │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.js │ │ ├── App.test.js │ │ ├── index.css │ │ ├── index.js │ │ ├── logo.svg │ │ ├── serviceWorker.js │ │ └── setupTests.js │ └── yarn.lock └── starter-project │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── generate-react-cli.json │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.test.tsx │ ├── App.tsx │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── react-app-env.d.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ └── component │ │ ├── component.js │ │ ├── style.scss │ │ └── test.js │ ├── tsconfig.json │ └── yarn.lock ├── Ch3 ├── .DS_Store └── WelcomeUser.html ├── Ch4 ├── .DS_Store ├── exercise-4-1 │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ │ ├── app.test.tsx │ │ ├── global.d.ts │ │ ├── jest.config.js │ │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── .DS_Store │ │ ├── App.scss │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── AppRouter.test.tsx │ │ ├── AppRouter.tsx │ │ ├── assets │ │ │ └── README │ │ ├── components │ │ │ └── README │ │ ├── features │ │ │ └── README │ │ ├── index.scss │ │ ├── index.tsx │ │ ├── layout │ │ │ ├── Footer │ │ │ │ ├── Footer.scss │ │ │ │ ├── Footer.test.tsx │ │ │ │ └── Footer.tsx │ │ │ ├── Header │ │ │ │ ├── Header.scss │ │ │ │ ├── Header.test.tsx │ │ │ │ └── Header.tsx │ │ │ └── README │ │ ├── logo.svg │ │ ├── model │ │ │ └── README │ │ ├── pages │ │ │ ├── ArticlesPage │ │ │ │ ├── ArticlesPage.scss │ │ │ │ ├── ArticlesPage.test.tsx │ │ │ │ └── ArticlesPage.tsx │ │ │ ├── BooksPage │ │ │ │ ├── BooksPage.scss │ │ │ │ ├── BooksPage.test.tsx │ │ │ │ └── BooksPage.tsx │ │ │ ├── BuildSiteCoursePage │ │ │ │ ├── BuildSiteCoursePage.scss │ │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ │ └── BuildSiteCoursePage.tsx │ │ │ ├── CoachingHourlyPage │ │ │ │ ├── CoachingHourlyPage.scss │ │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ │ └── CoachingHourlyPage.tsx │ │ │ ├── CoachingPackagePage │ │ │ │ ├── CoachingPackagePage.scss │ │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ │ └── CoachingPackagePage.tsx │ │ │ ├── ContactPage │ │ │ │ ├── ContactPage.scss │ │ │ │ ├── ContactPage.test.tsx │ │ │ │ └── ContactPage.tsx │ │ │ ├── HomePage │ │ │ │ ├── HomePage.scss │ │ │ │ ├── HomePage.test.tsx │ │ │ │ └── HomePage.tsx │ │ │ ├── LoginPage │ │ │ │ ├── LoginPage.scss │ │ │ │ ├── LoginPage.test.tsx │ │ │ │ └── LoginPage.tsx │ │ │ ├── MembersPage │ │ │ │ ├── MembersPage.scss │ │ │ │ ├── MembersPage.test.tsx │ │ │ │ └── MembersPage.tsx │ │ │ ├── NotFoundPage │ │ │ │ ├── NotFoundPage.scss │ │ │ │ ├── NotFoundPage.test.tsx │ │ │ │ └── NotFoundPage.tsx │ │ │ ├── README │ │ │ └── YouBuildMySitePage │ │ │ │ ├── YouBuildMySitePage.scss │ │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ │ └── YouBuildMySitePage.tsx │ │ ├── react-app-env.d.ts │ │ ├── recoil │ │ │ ├── atoms │ │ │ │ └── README │ │ │ └── selectors │ │ │ │ └── README │ │ ├── redux │ │ │ └── store.ts │ │ ├── serviceWorker.ts │ │ └── setupTests.ts │ ├── templates │ │ ├── component │ │ │ ├── component.js │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ ├── test.js │ │ │ └── test.tsx │ │ └── page │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock └── exercise-4-2 │ ├── .DS_Store │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── .DS_Store │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ └── README │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ ├── Footer │ │ │ ├── Footer.scss │ │ │ ├── Footer.test.tsx │ │ │ └── Footer.tsx │ │ ├── Header │ │ │ ├── Header.scss │ │ │ ├── Header.test.tsx │ │ │ ├── Header.tsx │ │ │ ├── HeaderDrawer.tsx │ │ │ ├── HeaderTheme.tsx │ │ │ └── HeaderTopNav.tsx │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ ├── ArticlesPage │ │ │ ├── ArticlesPage.scss │ │ │ ├── ArticlesPage.test.tsx │ │ │ └── ArticlesPage.tsx │ │ ├── BooksPage │ │ │ ├── BooksPage.scss │ │ │ ├── BooksPage.test.tsx │ │ │ └── BooksPage.tsx │ │ ├── BuildSiteCoursePage │ │ │ ├── BuildSiteCoursePage.scss │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ └── BuildSiteCoursePage.tsx │ │ ├── CoachingHourlyPage │ │ │ ├── CoachingHourlyPage.scss │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ └── CoachingHourlyPage.tsx │ │ ├── CoachingPackagePage │ │ │ ├── CoachingPackagePage.scss │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ └── CoachingPackagePage.tsx │ │ ├── ContactPage │ │ │ ├── ContactPage.scss │ │ │ ├── ContactPage.test.tsx │ │ │ └── ContactPage.tsx │ │ ├── HomePage │ │ │ ├── HomePage.scss │ │ │ ├── HomePage.test.tsx │ │ │ └── HomePage.tsx │ │ ├── LoginPage │ │ │ ├── LoginPage.scss │ │ │ ├── LoginPage.test.tsx │ │ │ └── LoginPage.tsx │ │ ├── MembersPage │ │ │ ├── MembersPage.scss │ │ │ ├── MembersPage.test.tsx │ │ │ └── MembersPage.tsx │ │ ├── NotFoundPage │ │ │ ├── NotFoundPage.scss │ │ │ ├── NotFoundPage.test.tsx │ │ │ └── NotFoundPage.tsx │ │ ├── README │ │ └── YouBuildMySitePage │ │ │ ├── YouBuildMySitePage.scss │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ └── YouBuildMySitePage.tsx │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock ├── Ch5 ├── .DS_Store ├── README.md ├── README_CRA.md ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js ├── generate-react-cli.json ├── jest-puppeteer.config.js ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt ├── src │ ├── .DS_Store │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.scss │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ └── README │ ├── features │ │ ├── Preferences │ │ │ └── preferencesSlice.ts │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ ├── Footer │ │ │ ├── Footer.scss │ │ │ ├── Footer.styles.ts │ │ │ ├── Footer.test.tsx │ │ │ ├── Footer.tsx │ │ │ └── FooterTheme.tsx │ │ ├── Header │ │ │ ├── Header.scss │ │ │ ├── Header.test.tsx │ │ │ ├── Header.tsx │ │ │ ├── HeaderDrawer.tsx │ │ │ ├── HeaderTheme.tsx │ │ │ └── HeaderTopNav.tsx │ │ └── README │ ├── logo.svg │ ├── model │ │ ├── README │ │ ├── index.ts │ │ └── preferencesObject.ts │ ├── pages │ │ ├── ArticlesPage │ │ │ ├── ArticlesPage.scss │ │ │ ├── ArticlesPage.test.tsx │ │ │ └── ArticlesPage.tsx │ │ ├── BooksPage │ │ │ ├── BooksPage.scss │ │ │ ├── BooksPage.test.tsx │ │ │ └── BooksPage.tsx │ │ ├── BuildSiteCoursePage │ │ │ ├── BuildSiteCoursePage.scss │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ └── BuildSiteCoursePage.tsx │ │ ├── CoachingHourlyPage │ │ │ ├── CoachingHourlyPage.scss │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ └── CoachingHourlyPage.tsx │ │ ├── CoachingPackagePage │ │ │ ├── CoachingPackagePage.scss │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ └── CoachingPackagePage.tsx │ │ ├── ContactPage │ │ │ ├── ContactPage.scss │ │ │ ├── ContactPage.test.tsx │ │ │ └── ContactPage.tsx │ │ ├── HomePage │ │ │ ├── HomePage.scss │ │ │ ├── HomePage.test.tsx │ │ │ └── HomePage.tsx │ │ ├── LoginPage │ │ │ ├── LoginPage.scss │ │ │ ├── LoginPage.test.tsx │ │ │ └── LoginPage.tsx │ │ ├── MembersPage │ │ │ ├── MembersPage.scss │ │ │ ├── MembersPage.test.tsx │ │ │ └── MembersPage.tsx │ │ ├── NotFoundPage │ │ │ ├── NotFoundPage.scss │ │ │ ├── NotFoundPage.test.tsx │ │ │ └── NotFoundPage.tsx │ │ ├── README │ │ └── YouBuildMySitePage │ │ │ ├── YouBuildMySitePage.scss │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ └── YouBuildMySitePage.tsx │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx ├── tsconfig.json └── yarn.lock ├── Ch6 ├── exercise-6-1 │ ├── .DS_Store │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ │ ├── app.test.tsx │ │ ├── global.d.ts │ │ ├── jest.config.js │ │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── .DS_Store │ │ ├── App.scss │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── AppRouter.scss │ │ ├── AppRouter.test.tsx │ │ ├── AppRouter.tsx │ │ ├── assets │ │ │ └── README │ │ ├── components │ │ │ ├── README │ │ │ ├── UserButton │ │ │ │ ├── UserButton.scss │ │ │ │ └── UserButton.tsx │ │ │ └── UserListButton │ │ │ │ └── UserListButton.tsx │ │ ├── features │ │ │ └── README │ │ ├── index.scss │ │ ├── index.tsx │ │ ├── layout │ │ │ ├── Footer │ │ │ │ ├── Footer.scss │ │ │ │ ├── Footer.styles.ts │ │ │ │ ├── Footer.test.tsx │ │ │ │ ├── Footer.tsx │ │ │ │ └── FooterTheme.tsx │ │ │ ├── Header │ │ │ │ ├── Header.scss │ │ │ │ ├── Header.test.tsx │ │ │ │ ├── Header.tsx │ │ │ │ ├── HeaderDrawer.tsx │ │ │ │ ├── HeaderTheme.tsx │ │ │ │ └── HeaderTopNav.tsx │ │ │ └── README │ │ ├── logo.svg │ │ ├── model │ │ │ ├── README │ │ │ ├── index.ts │ │ │ └── preferencesObject.ts │ │ ├── pages │ │ │ ├── ArticlesPage │ │ │ │ ├── ArticlesPage.scss │ │ │ │ ├── ArticlesPage.test.tsx │ │ │ │ └── ArticlesPage.tsx │ │ │ ├── BooksPage │ │ │ │ ├── BooksPage.scss │ │ │ │ ├── BooksPage.test.tsx │ │ │ │ └── BooksPage.tsx │ │ │ ├── BuildSiteCoursePage │ │ │ │ ├── BuildSiteCoursePage.scss │ │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ │ └── BuildSiteCoursePage.tsx │ │ │ ├── CoachingHourlyPage │ │ │ │ ├── CoachingHourlyPage.scss │ │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ │ └── CoachingHourlyPage.tsx │ │ │ ├── CoachingPackagePage │ │ │ │ ├── CoachingPackagePage.scss │ │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ │ └── CoachingPackagePage.tsx │ │ │ ├── ContactPage │ │ │ │ ├── ContactPage.scss │ │ │ │ ├── ContactPage.test.tsx │ │ │ │ └── ContactPage.tsx │ │ │ ├── HomePage │ │ │ │ ├── HomePage.scss │ │ │ │ ├── HomePage.test.tsx │ │ │ │ └── HomePage.tsx │ │ │ ├── LoginPage │ │ │ │ ├── LoginPage.scss │ │ │ │ ├── LoginPage.test.tsx │ │ │ │ └── LoginPage.tsx │ │ │ ├── MembersPage │ │ │ │ ├── MembersPage.scss │ │ │ │ ├── MembersPage.test.tsx │ │ │ │ └── MembersPage.tsx │ │ │ ├── NotFoundPage │ │ │ │ ├── NotFoundPage.scss │ │ │ │ ├── NotFoundPage.test.tsx │ │ │ │ └── NotFoundPage.tsx │ │ │ ├── README │ │ │ └── YouBuildMySitePage │ │ │ │ ├── YouBuildMySitePage.scss │ │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ │ └── YouBuildMySitePage.tsx │ │ ├── react-app-env.d.ts │ │ ├── recoil │ │ │ ├── atoms │ │ │ │ ├── README │ │ │ │ ├── preferencesAtoms.ts │ │ │ │ └── sessionAtoms.ts │ │ │ └── selectors │ │ │ │ └── README │ │ ├── serviceWorker.ts │ │ └── setupTests.ts │ ├── templates │ │ ├── component │ │ │ ├── component.js │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ ├── test.js │ │ │ └── test.tsx │ │ └── page │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock ├── exercise-6-2 │ ├── .DS_Store │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ │ ├── app.test.tsx │ │ ├── global.d.ts │ │ ├── jest.config.js │ │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── .DS_Store │ │ ├── App.scss │ │ ├── App.test.tsx │ │ ├── App.tsx │ │ ├── AppRouter.scss │ │ ├── AppRouter.test.tsx │ │ ├── AppRouter.tsx │ │ ├── assets │ │ │ ├── README │ │ │ └── toast │ │ │ │ ├── check.svg │ │ │ │ ├── error.svg │ │ │ │ ├── info.svg │ │ │ │ └── warning.svg │ │ ├── components │ │ │ ├── README │ │ │ ├── Toast │ │ │ │ ├── Toast.scss │ │ │ │ ├── Toast.tsx │ │ │ │ ├── ToastNotification.scss │ │ │ │ └── ToastNotification.tsx │ │ │ ├── UserButton │ │ │ │ ├── UserButton.scss │ │ │ │ └── UserButton.tsx │ │ │ └── UserListButton │ │ │ │ └── UserListButton.tsx │ │ ├── features │ │ │ └── README │ │ ├── index.scss │ │ ├── index.tsx │ │ ├── layout │ │ │ ├── Footer │ │ │ │ ├── Footer.scss │ │ │ │ ├── Footer.styles.ts │ │ │ │ ├── Footer.test.tsx │ │ │ │ ├── Footer.tsx │ │ │ │ └── FooterTheme.tsx │ │ │ ├── Header │ │ │ │ ├── Header.scss │ │ │ │ ├── Header.test.tsx │ │ │ │ ├── Header.tsx │ │ │ │ ├── HeaderDrawer.tsx │ │ │ │ ├── HeaderTheme.tsx │ │ │ │ └── HeaderTopNav.tsx │ │ │ └── README │ │ ├── logo.svg │ │ ├── model │ │ │ ├── README │ │ │ ├── index.ts │ │ │ ├── preferencesObject.ts │ │ │ └── toastObject.ts │ │ ├── pages │ │ │ ├── ArticlesPage │ │ │ │ ├── ArticlesPage.scss │ │ │ │ ├── ArticlesPage.test.tsx │ │ │ │ └── ArticlesPage.tsx │ │ │ ├── BooksPage │ │ │ │ ├── BooksPage.scss │ │ │ │ ├── BooksPage.test.tsx │ │ │ │ └── BooksPage.tsx │ │ │ ├── BuildSiteCoursePage │ │ │ │ ├── BuildSiteCoursePage.scss │ │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ │ └── BuildSiteCoursePage.tsx │ │ │ ├── CoachingHourlyPage │ │ │ │ ├── CoachingHourlyPage.scss │ │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ │ └── CoachingHourlyPage.tsx │ │ │ ├── CoachingPackagePage │ │ │ │ ├── CoachingPackagePage.scss │ │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ │ └── CoachingPackagePage.tsx │ │ │ ├── ContactPage │ │ │ │ ├── ContactPage.scss │ │ │ │ ├── ContactPage.test.tsx │ │ │ │ └── ContactPage.tsx │ │ │ ├── HomePage │ │ │ │ ├── HomePage.scss │ │ │ │ ├── HomePage.test.tsx │ │ │ │ └── HomePage.tsx │ │ │ ├── LoginPage │ │ │ │ ├── LoginPage.scss │ │ │ │ ├── LoginPage.test.tsx │ │ │ │ └── LoginPage.tsx │ │ │ ├── MembersPage │ │ │ │ ├── MembersPage.scss │ │ │ │ ├── MembersPage.test.tsx │ │ │ │ └── MembersPage.tsx │ │ │ ├── NotFoundPage │ │ │ │ ├── NotFoundPage.scss │ │ │ │ ├── NotFoundPage.test.tsx │ │ │ │ └── NotFoundPage.tsx │ │ │ ├── README │ │ │ └── YouBuildMySitePage │ │ │ │ ├── YouBuildMySitePage.scss │ │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ │ └── YouBuildMySitePage.tsx │ │ ├── react-app-env.d.ts │ │ ├── recoil │ │ │ ├── atoms │ │ │ │ ├── README │ │ │ │ ├── preferencesAtoms.ts │ │ │ │ ├── sessionAtoms.ts │ │ │ │ └── toastAtoms.ts │ │ │ └── selectors │ │ │ │ └── README │ │ ├── serviceWorker.ts │ │ └── setupTests.ts │ ├── templates │ │ ├── component │ │ │ ├── component.js │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ ├── test.js │ │ │ └── test.tsx │ │ └── page │ │ │ ├── component.tsx │ │ │ ├── style.scss │ │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock └── exercise-6-3 │ ├── .DS_Store │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── .DS_Store │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.scss │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ ├── README │ │ └── toast │ │ │ ├── check.svg │ │ │ ├── error.svg │ │ │ ├── info.svg │ │ │ └── warning.svg │ ├── components │ │ ├── Login │ │ │ ├── LoginForm.styles.ts │ │ │ └── LoginForm.tsx │ │ ├── README │ │ ├── Toast │ │ │ ├── Toast.scss │ │ │ ├── Toast.tsx │ │ │ ├── ToastNotification.scss │ │ │ └── ToastNotification.tsx │ │ ├── UserButton │ │ │ ├── UserButton.scss │ │ │ └── UserButton.tsx │ │ └── UserListButton │ │ │ └── UserListButton.tsx │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ ├── Centered │ │ │ ├── Centered.styles.ts │ │ │ ├── Centered.tsx │ │ │ └── index.ts │ │ ├── Footer │ │ │ ├── Footer.scss │ │ │ ├── Footer.styles.ts │ │ │ ├── Footer.test.tsx │ │ │ ├── Footer.tsx │ │ │ └── FooterTheme.tsx │ │ ├── Header │ │ │ ├── Header.scss │ │ │ ├── Header.test.tsx │ │ │ ├── Header.tsx │ │ │ ├── HeaderDrawer.tsx │ │ │ ├── HeaderTheme.tsx │ │ │ └── HeaderTopNav.tsx │ │ └── README │ ├── logo.svg │ ├── model │ │ ├── README │ │ ├── index.ts │ │ ├── preferencesObject.ts │ │ ├── toastObject.ts │ │ └── userObject.ts │ ├── pages │ │ ├── ArticlesPage │ │ │ ├── ArticlesPage.scss │ │ │ ├── ArticlesPage.test.tsx │ │ │ └── ArticlesPage.tsx │ │ ├── BooksPage │ │ │ ├── BooksPage.scss │ │ │ ├── BooksPage.test.tsx │ │ │ └── BooksPage.tsx │ │ ├── BuildSiteCoursePage │ │ │ ├── BuildSiteCoursePage.scss │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ └── BuildSiteCoursePage.tsx │ │ ├── CoachingHourlyPage │ │ │ ├── CoachingHourlyPage.scss │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ └── CoachingHourlyPage.tsx │ │ ├── CoachingPackagePage │ │ │ ├── CoachingPackagePage.scss │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ └── CoachingPackagePage.tsx │ │ ├── ContactPage │ │ │ ├── ContactPage.scss │ │ │ ├── ContactPage.test.tsx │ │ │ └── ContactPage.tsx │ │ ├── HomePage │ │ │ ├── HomePage.scss │ │ │ ├── HomePage.test.tsx │ │ │ └── HomePage.tsx │ │ ├── LoginPage │ │ │ ├── LoginPage.scss │ │ │ ├── LoginPage.test.tsx │ │ │ └── LoginPage.tsx │ │ ├── MembersPage │ │ │ ├── MembersHome.tsx │ │ │ ├── MembersPage.scss │ │ │ └── MembersPage.tsx │ │ ├── NotFoundPage │ │ │ ├── NotFoundPage.scss │ │ │ ├── NotFoundPage.test.tsx │ │ │ └── NotFoundPage.tsx │ │ ├── README │ │ └── YouBuildMySitePage │ │ │ ├── YouBuildMySitePage.scss │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ └── YouBuildMySitePage.tsx │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ ├── README │ │ │ ├── preferencesAtoms.ts │ │ │ ├── sessionAtoms.ts │ │ │ ├── toastAtoms.ts │ │ │ └── userAtoms.ts │ │ └── selectors │ │ │ ├── README │ │ │ └── userSelectors.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock ├── Ch7 ├── .DS_Store ├── exercise-7-1 │ ├── .DS_Store │ ├── config.json │ ├── logs │ │ ├── server-error.log │ │ └── server.log │ ├── models │ │ └── database.js │ ├── package-lock.json │ ├── package.json │ ├── roomsdb-local.json │ ├── roomsdb.json │ ├── server.js │ ├── services │ │ ├── register.js │ │ └── validate.js │ └── utils │ │ └── log.js └── exercise-7-2 │ ├── .DS_Store │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── .DS_Store │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.scss │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ ├── README │ │ └── toast │ │ │ ├── check.svg │ │ │ ├── error.svg │ │ │ ├── info.svg │ │ │ └── warning.svg │ ├── components │ │ ├── Login │ │ │ ├── LoginForm.styles.ts │ │ │ └── LoginForm.tsx │ │ ├── README │ │ ├── Register │ │ │ ├── RegisterForm.styles.ts │ │ │ └── RegisterForm.tsx │ │ ├── Toast │ │ │ ├── Toast.scss │ │ │ ├── Toast.tsx │ │ │ ├── ToastNotification.scss │ │ │ └── ToastNotification.tsx │ │ ├── UserButton │ │ │ ├── UserButton.scss │ │ │ └── UserButton.tsx │ │ └── UserListButton │ │ │ └── UserListButton.tsx │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ ├── Centered │ │ │ ├── Centered.styles.ts │ │ │ ├── Centered.tsx │ │ │ └── index.ts │ │ ├── Footer │ │ │ ├── Footer.scss │ │ │ ├── Footer.styles.ts │ │ │ ├── Footer.test.tsx │ │ │ ├── Footer.tsx │ │ │ └── FooterTheme.tsx │ │ ├── Header │ │ │ ├── Header.scss │ │ │ ├── Header.test.tsx │ │ │ ├── Header.tsx │ │ │ ├── HeaderDrawer.tsx │ │ │ ├── HeaderTheme.tsx │ │ │ └── HeaderTopNav.tsx │ │ └── README │ ├── logo.svg │ ├── model │ │ ├── README │ │ ├── index.ts │ │ ├── preferencesObject.ts │ │ ├── registerObject.ts │ │ ├── toastObject.ts │ │ └── userObject.ts │ ├── pages │ │ ├── ArticlesPage │ │ │ ├── ArticlesPage.scss │ │ │ ├── ArticlesPage.test.tsx │ │ │ └── ArticlesPage.tsx │ │ ├── BooksPage │ │ │ ├── BooksPage.scss │ │ │ ├── BooksPage.test.tsx │ │ │ └── BooksPage.tsx │ │ ├── BuildSiteCoursePage │ │ │ ├── BuildSiteCoursePage.scss │ │ │ ├── BuildSiteCoursePage.test.tsx │ │ │ └── BuildSiteCoursePage.tsx │ │ ├── CoachingHourlyPage │ │ │ ├── CoachingHourlyPage.scss │ │ │ ├── CoachingHourlyPage.test.tsx │ │ │ └── CoachingHourlyPage.tsx │ │ ├── CoachingPackagePage │ │ │ ├── CoachingPackagePage.scss │ │ │ ├── CoachingPackagePage.test.tsx │ │ │ └── CoachingPackagePage.tsx │ │ ├── ContactPage │ │ │ ├── ContactPage.scss │ │ │ ├── ContactPage.test.tsx │ │ │ └── ContactPage.tsx │ │ ├── HomePage │ │ │ ├── HomePage.scss │ │ │ ├── HomePage.test.tsx │ │ │ └── HomePage.tsx │ │ ├── LoginPage │ │ │ ├── LoginPage.scss │ │ │ ├── LoginPage.test.tsx │ │ │ └── LoginPage.tsx │ │ ├── MembersPage │ │ │ ├── MembersHome.tsx │ │ │ ├── MembersPage.scss │ │ │ └── MembersPage.tsx │ │ ├── NotFoundPage │ │ │ ├── NotFoundPage.scss │ │ │ ├── NotFoundPage.test.tsx │ │ │ └── NotFoundPage.tsx │ │ ├── README │ │ ├── RegisterPage │ │ │ ├── RegisterPage.scss │ │ │ ├── RegisterPage.test.tsx │ │ │ └── RegisterPage.tsx │ │ └── YouBuildMySitePage │ │ │ ├── YouBuildMySitePage.scss │ │ │ ├── YouBuildMySitePage.test.tsx │ │ │ └── YouBuildMySitePage.tsx │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ ├── README │ │ │ ├── preferencesAtoms.ts │ │ │ ├── registerAtoms.ts │ │ │ ├── sessionAtoms.ts │ │ │ ├── toastAtoms.ts │ │ │ └── userAtoms.ts │ │ └── selectors │ │ │ ├── README │ │ │ ├── registerSelectors.ts │ │ │ └── userSelectors.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ ├── tsconfig.json │ └── yarn.lock ├── Ch8 ├── .DS_Store ├── api │ └── Gruntfile.js └── app │ ├── .DS_Store │ └── Gruntfile.js ├── Ch9 ├── .DS_Store └── hello-jest-enzyme-ts │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── README.md │ ├── README_CRA.md │ ├── e2e │ ├── app.test.tsx │ ├── global.d.ts │ ├── jest.config.js │ └── puppeteer_standalone.js │ ├── generate-react-cli.json │ ├── jest-puppeteer.config.js │ ├── package.json │ ├── public │ ├── calculator-input.jpg │ ├── calculator.jpg │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.scss │ ├── App.test.tsx │ ├── App.tsx │ ├── AppRouter.test.tsx │ ├── AppRouter.tsx │ ├── assets │ │ └── README │ ├── components │ │ ├── Calculator │ │ │ ├── Calculator.scss │ │ │ ├── Calculator.test.tsx │ │ │ ├── Calculator.tsx │ │ │ └── __snapshots__ │ │ │ │ └── Calculator.test.tsx.snap │ │ └── README │ ├── features │ │ └── README │ ├── index.scss │ ├── index.tsx │ ├── layout │ │ └── README │ ├── logo.svg │ ├── model │ │ └── README │ ├── pages │ │ └── README │ ├── react-app-env.d.ts │ ├── recoil │ │ ├── atoms │ │ │ └── README │ │ └── selectors │ │ │ └── README │ ├── redux │ │ └── store.ts │ ├── serviceWorker.ts │ └── setupTests.ts │ ├── templates │ ├── component │ │ ├── component.js │ │ ├── component.tsx │ │ ├── style.scss │ │ ├── test.js │ │ └── test.tsx │ └── page │ │ ├── component.tsx │ │ ├── style.scss │ │ └── test.tsx │ └── tsconfig.json ├── Contributing.md ├── LICENSE.txt ├── README.md └── errata.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /9781484266953.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/9781484266953.jpg -------------------------------------------------------------------------------- /Ch1/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch1/.DS_Store -------------------------------------------------------------------------------- /Ch1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hello world 5 | 6 | 7 | 9 | 10 | 11 |
12 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Ch10/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/.DS_Store -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | BROWSER=none 3 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/.eslintignore: -------------------------------------------------------------------------------- 1 | build/* 2 | public/* 3 | docs/* 4 | templates/* 5 | src/react-app-env.d.ts 6 | src/serviceWorker.ts 7 | e2e/jest.config.js 8 | e2e/puppeteer_standalone.js 9 | jest-puppeteer.config.js -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | package-lock.json 4 | yarn-error.log 5 | yarn.lock 6 | docs 7 | 8 | # IDE 9 | .idea 10 | 11 | # dependencies 12 | /node_modules 13 | /.pnp 14 | .pnp.js 15 | 16 | # testing 17 | /coverage 18 | .nyc_output 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | .env.local 26 | .env.development.local 27 | .env.test.local 28 | .env.production.local 29 | 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 100, 4 | "semi": false, 5 | "singleQuote": true, 6 | "tabWidth": 2 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 30000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/e2e_ts_testing_with_puppeteer/public/favicon.ico -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/e2e_ts_testing_with_puppeteer/public/logo192.png -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch10/e2e_ts_testing_with_puppeteer/public/logo512.png -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/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 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/App.scss: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import logo from './logo.svg' 3 | import './App.scss' 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Eli Elad Elrom - React Tutorials 20 | 21 |
22 |
23 | ) 24 | } 25 | 26 | export default App 27 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component UserButton -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 11 | } 12 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/model/README: -------------------------------------------------------------------------------- 1 | place all your object model files here, for example: userObject.ts 2 | 3 | export interface userObject { 4 | email: string 5 | password: string 6 | } 7 | 8 | export const initUser = (): userObject => ({ 9 | email: '', 10 | password: '', 11 | }) 12 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | // src/recoil/atoms/userAtoms.ts 4 | import { atom } from 'recoil' 5 | import { initUser } from '../../model' 6 | 7 | export const userState = atom({ 8 | key: 'UserState', 9 | default: initUser(), 10 | }) -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/src/setupTests.ts: -------------------------------------------------------------------------------- 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/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { shallow } from 'enzyme' 3 | import TemplateName from './TemplateName' 4 | 5 | describe('', () => { 6 | let component 7 | 8 | beforeEach(() => { 9 | component = shallow() 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | -------------------------------------------------------------------------------- /Ch10/e2e_ts_testing_with_puppeteer/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /Ch12/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true 2 | BROWSER=none 3 | -------------------------------------------------------------------------------- /Ch12/.eslintignore: -------------------------------------------------------------------------------- 1 | build/* 2 | public/* 3 | docs/* 4 | templates/* 5 | src/react-app-env.d.ts 6 | src/serviceWorker.ts 7 | e2e/jest.config.js 8 | e2e/puppeteer_standalone.js 9 | jest-puppeteer.config.js -------------------------------------------------------------------------------- /Ch12/.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | package-lock.json 4 | yarn-error.log 5 | yarn.lock 6 | docs 7 | 8 | # IDEs 9 | .vscode 10 | .idea 11 | 12 | # dependencies 13 | /node_modules 14 | /.pnp 15 | .pnp.js 16 | 17 | # testing 18 | /coverage 19 | .nyc_output 20 | 21 | # production 22 | /build 23 | 24 | # misc 25 | .DS_Store 26 | .env.local 27 | .env.development.local 28 | .env.test.local 29 | .env.production.local 30 | 31 | npm-debug.log* 32 | yarn-debug.log* 33 | yarn-error.log* 34 | -------------------------------------------------------------------------------- /Ch12/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 100, 4 | "semi": false, 5 | "singleQuote": true, 6 | "tabWidth": 2 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Ch12/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /Ch12/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 10000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /Ch12/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /Ch12/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch12/public/favicon.ico -------------------------------------------------------------------------------- /Ch12/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch12/public/logo192.png -------------------------------------------------------------------------------- /Ch12/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch12/public/logo512.png -------------------------------------------------------------------------------- /Ch12/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 | -------------------------------------------------------------------------------- /Ch12/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Ch12/src/App.scss: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Ch12/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /Ch12/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /Ch12/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /Ch12/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component UserButton -------------------------------------------------------------------------------- /Ch12/src/components/ScrollToTop/ScrollToTop.tsx: -------------------------------------------------------------------------------- 1 | // src/components/ScrollToTop/ScrollToTop.tsx 2 | 3 | import { useEffect } from 'react' 4 | import { useLocation } from 'react-router-dom' 5 | 6 | export default function ScrollToTop() { 7 | const { pathname, search } = useLocation() 8 | 9 | useEffect( 10 | () => () => { 11 | try { 12 | window.scroll({ 13 | top: 0, 14 | left: 0, 15 | behavior: 'smooth', 16 | }) 17 | } catch (error) { 18 | // older browsers fallback 19 | window.scrollTo(0, 0) 20 | } 21 | }, 22 | [pathname, search] 23 | ) 24 | return null 25 | } 26 | -------------------------------------------------------------------------------- /Ch12/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /Ch12/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 11 | } 12 | -------------------------------------------------------------------------------- /Ch12/src/layout/README: -------------------------------------------------------------------------------- 1 | layout components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component BoxLayout --type=layout -------------------------------------------------------------------------------- /Ch12/src/model/README: -------------------------------------------------------------------------------- 1 | place all your object model files here, for example: userObject.ts 2 | 3 | export interface userObject { 4 | email: string 5 | password: string 6 | } 7 | 8 | export const initUser = (): userObject => ({ 9 | email: '', 10 | password: '', 11 | }) 12 | -------------------------------------------------------------------------------- /Ch12/src/pages/MyPage/MyPage.scss: -------------------------------------------------------------------------------- 1 | .MyPage { 2 | } 3 | -------------------------------------------------------------------------------- /Ch12/src/pages/MyPage/MyPage.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { shallow } from 'enzyme' 3 | import MyPage from './MyPage' 4 | 5 | const routeComponentPropsMock = { 6 | history: { 7 | location: { 8 | pathname: '/MyPage', 9 | }, 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | } as any, 12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 13 | location: {} as any, 14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 15 | match: {} as any, 16 | } 17 | describe('', () => { 18 | let component 19 | 20 | beforeEach(() => { 21 | component = shallow() 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /Ch12/src/pages/MyPage/math.tsx: -------------------------------------------------------------------------------- 1 | // src/page/MyPage/math.tsx 2 | 3 | export function square(x: number) { 4 | return x * x 5 | } 6 | 7 | export function cube(x: number) { 8 | return x * x * x 9 | } 10 | 11 | export function add(x: number, y: number) { 12 | return x + y 13 | } 14 | -------------------------------------------------------------------------------- /Ch12/src/pages/README: -------------------------------------------------------------------------------- 1 | Pages components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component HomePage --type=page -------------------------------------------------------------------------------- /Ch12/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Ch12/src/recoil/atoms/README: -------------------------------------------------------------------------------- 1 | Recoil atoms goes here, example: userAtoms.ts; 2 | 3 | // src/recoil/atoms/userAtoms.ts 4 | import { atom } from 'recoil' 5 | import { initUser } from '../../model' 6 | 7 | export const userState = atom({ 8 | key: 'UserState', 9 | default: initUser(), 10 | }) -------------------------------------------------------------------------------- /Ch12/src/redux/store.ts: -------------------------------------------------------------------------------- 1 | // src/redux/store.ts 2 | 3 | import { configureStore, combineReducers } from '@reduxjs/toolkit' 4 | 5 | const store = configureStore({ 6 | reducer: combineReducers({ 7 | // your reducers goes here 8 | }), 9 | }) 10 | 11 | export default store 12 | -------------------------------------------------------------------------------- /Ch12/src/setupTests.ts: -------------------------------------------------------------------------------- 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/extend-expect' 6 | 7 | import { configure } from 'enzyme' 8 | import Adapter from 'enzyme-adapter-react-16' 9 | 10 | configure({ adapter: new Adapter() }) 11 | -------------------------------------------------------------------------------- /Ch12/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /Ch12/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /Ch12/templates/component/test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /Ch12/templates/page/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | } -------------------------------------------------------------------------------- /Ch12/templates/page/test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | const routeComponentPropsMock = { 6 | history: { 7 | location: { 8 | pathname: '/TemplateName' 9 | } 10 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 11 | } as any, 12 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 13 | location: {} as any, 14 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 15 | match: {} as any, 16 | } 17 | describe('', () => { 18 | let component 19 | 20 | beforeEach(() => { 21 | component = shallow() 22 | }) 23 | 24 | test('It should mount', () => { 25 | expect(component.length).toBe(1) 26 | }) 27 | }) 28 | -------------------------------------------------------------------------------- /Ch2/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/.DS_Store -------------------------------------------------------------------------------- /Ch2/hello-cra/.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 | -------------------------------------------------------------------------------- /Ch2/hello-cra/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/hello-cra/public/favicon.ico -------------------------------------------------------------------------------- /Ch2/hello-cra/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/hello-cra/public/logo192.png -------------------------------------------------------------------------------- /Ch2/hello-cra/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/hello-cra/public/logo512.png -------------------------------------------------------------------------------- /Ch2/hello-cra/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 | -------------------------------------------------------------------------------- /Ch2/hello-cra/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: -------------------------------------------------------------------------------- /Ch2/hello-cra/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 | -------------------------------------------------------------------------------- /Ch2/hello-cra/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import logo from './logo.svg'; 3 | import './App.css'; 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.js and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ); 24 | } 25 | 26 | export default App; 27 | -------------------------------------------------------------------------------- /Ch2/hello-cra/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /Ch2/hello-cra/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 | -------------------------------------------------------------------------------- /Ch2/hello-cra/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /Ch2/hello-cra/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/extend-expect'; 6 | -------------------------------------------------------------------------------- /Ch2/starter-project/.gitignore: -------------------------------------------------------------------------------- 1 | # misc 2 | .DS_Store 3 | package-lock.json 4 | docs 5 | 6 | # IDE 7 | .idea 8 | 9 | # dependencies 10 | /node_modules 11 | 12 | # dependencies 13 | /node_modules 14 | /.pnp 15 | .pnp.js 16 | 17 | # testing 18 | /coverage 19 | 20 | # production 21 | /build 22 | 23 | # misc 24 | .DS_Store 25 | .env.local 26 | .env.development.local 27 | .env.test.local 28 | .env.production.local 29 | 30 | npm-debug.log* 31 | yarn-debug.log* 32 | yarn-error.log* 33 | -------------------------------------------------------------------------------- /Ch2/starter-project/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "printWidth": 100, 4 | "semi": false, 5 | "singleQuote": true, 6 | "tabWidth": 2 7 | } 8 | 9 | -------------------------------------------------------------------------------- /Ch2/starter-project/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/starter-project/public/favicon.ico -------------------------------------------------------------------------------- /Ch2/starter-project/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/starter-project/public/logo192.png -------------------------------------------------------------------------------- /Ch2/starter-project/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch2/starter-project/public/logo512.png -------------------------------------------------------------------------------- /Ch2/starter-project/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 | -------------------------------------------------------------------------------- /Ch2/starter-project/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Ch2/starter-project/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 | -------------------------------------------------------------------------------- /Ch2/starter-project/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from '@testing-library/react' 3 | import App from './App' 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render() 7 | const linkElement = getByText(/learn react/i) 8 | expect(linkElement).toBeInTheDocument() 9 | }) 10 | -------------------------------------------------------------------------------- /Ch2/starter-project/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import logo from './logo.svg' 3 | import './App.css' 4 | 5 | function App() { 6 | return ( 7 |
8 |
9 | logo 10 |

11 | Edit src/App.tsx and save to reload. 12 |

13 | 19 | Learn React 20 | 21 |
22 |
23 | ) 24 | } 25 | 26 | export default App 27 | -------------------------------------------------------------------------------- /Ch2/starter-project/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 4 | 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | } 8 | 9 | code { 10 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 11 | } 12 | -------------------------------------------------------------------------------- /Ch2/starter-project/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import './index.css' 4 | import App from './App' 5 | import * as serviceWorker from './serviceWorker' 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ) 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister() 18 | -------------------------------------------------------------------------------- /Ch2/starter-project/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Ch2/starter-project/src/setupTests.ts: -------------------------------------------------------------------------------- 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/extend-expect' 6 | -------------------------------------------------------------------------------- /Ch2/starter-project/templates/component/style.scss: -------------------------------------------------------------------------------- 1 | .TemplateName { 2 | font-family: 'Open Sans', sans-serif; 3 | font-weight: 700; 4 | } -------------------------------------------------------------------------------- /Ch2/starter-project/templates/component/test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { shallow } from 'enzyme'; 3 | import TemplateName from './TemplateName'; 4 | 5 | describe('', () => { 6 | let component; 7 | 8 | beforeEach(() => { 9 | component = shallow(); 10 | }); 11 | 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /Ch2/starter-project/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "es6", "dom", 6 | "dom", 7 | "dom.iterable", 8 | "esnext" 9 | ], 10 | "noImplicitAny": true, 11 | "noImplicitThis": true, 12 | "strictNullChecks": true, 13 | "allowJs": true, 14 | "skipLibCheck": true, 15 | "esModuleInterop": true, 16 | "allowSyntheticDefaultImports": true, 17 | "strict": true, 18 | "forceConsistentCasingInFileNames": true, 19 | "module": "esnext", 20 | "moduleResolution": "node", 21 | "resolveJsonModule": true, 22 | "isolatedModules": true, 23 | "noEmit": true, 24 | "jsx": "react" 25 | }, 26 | "include": [ 27 | "src" 28 | ] 29 | } 30 | 31 | -------------------------------------------------------------------------------- /Ch3/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch3/.DS_Store -------------------------------------------------------------------------------- /Ch3/WelcomeUser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hi 5 | 6 | 7 | 9 | 10 | 11 |
12 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Ch4/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/.DS_Store -------------------------------------------------------------------------------- /Ch4/exercise-4-1/e2e/global.d.ts: -------------------------------------------------------------------------------- 1 | // globals defined in jest.config.js need to be included in this `d.ts` 2 | // file to avoid TS lint errors 3 | declare let SERVER_URL: string 4 | declare let JEST_TIMEOUT: number -------------------------------------------------------------------------------- /Ch4/exercise-4-1/e2e/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'jest-puppeteer', 3 | globals: { 4 | SERVER_URL: 'http://localhost:3000', 5 | JEST_TIMEOUT: 30000 6 | }, 7 | testRegex: './*\\.test\\.tsx$' 8 | } 9 | console.log('RUNNING E2E INTEGRATION TESTS - MAKE SURE PORT 3000 IS NOT IN USAGE') -------------------------------------------------------------------------------- /Ch4/exercise-4-1/jest-puppeteer.config.js: -------------------------------------------------------------------------------- 1 | // jest-puppeteer.config.js 2 | module.exports = { 3 | server: { 4 | command: `yarn start`, 5 | port: 3000, 6 | launchTimeout: 20000, 7 | debug: true, 8 | }, 9 | } 10 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/public/favicon.ico -------------------------------------------------------------------------------- /Ch4/exercise-4-1/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/public/logo192.png -------------------------------------------------------------------------------- /Ch4/exercise-4-1/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/public/logo512.png -------------------------------------------------------------------------------- /Ch4/exercise-4-1/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 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Apress/react-and-libraries/a3d5f5fe5ccd7d5048cfdebf7c337017f6916a01/Ch4/exercise-4-1/src/.DS_Store -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/App.scss: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | // src/App.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import App from './App' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | test('It should mount', () => { 13 | expect(component.length).toBe(1) 14 | }) 15 | }) 16 | 17 | /* 18 | Update this file once it's changed. For instance to check if a component you added 19 | include in App.tsx; 20 | 21 | import { shallow } from "enzyme"; 22 | import Calculator from "./components/SomeComponent/SomeComponent"; 23 | 24 | test('should render SomeComponent', () => { 25 | const wrapper = shallow(); 26 | const calculator = wrapper.find(SomeComponent); 27 | expect(calculator.exists()).toBe(true); 28 | }) 29 | */ 30 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/App.tsx: -------------------------------------------------------------------------------- 1 | // src/App.tsx 2 | 3 | import React from 'react' 4 | import './App.scss' 5 | 6 | function App() { 7 | return ( 8 |
9 |
App page
10 |
11 | ) 12 | } 13 | 14 | export default App 15 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/AppRouter.test.tsx: -------------------------------------------------------------------------------- 1 | // src/AppRouter.test.tsx 2 | import React from 'react' 3 | import { shallow } from 'enzyme' 4 | import AppRouter from './AppRouter' 5 | 6 | describe('', () => { 7 | let component 8 | 9 | beforeEach(() => { 10 | component = shallow() 11 | }) 12 | 13 | test('renders without crashing', () => { 14 | expect(component.length).toBe(1) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/assets/README: -------------------------------------------------------------------------------- 1 | Break down your assets by names: about, home, etc. -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/components/README: -------------------------------------------------------------------------------- 1 | components goes here, you can generate with generate-react-cli, example; 2 | $ npx generate-react-cli component UserButton -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/features/README: -------------------------------------------------------------------------------- 1 | features components goes here. -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/index.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; 4 | -webkit-font-smoothing: antialiased; 5 | -moz-osx-font-smoothing: grayscale; 6 | } 7 | 8 | code { 9 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', monospace; 10 | } 11 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/layout/Footer/Footer.scss: -------------------------------------------------------------------------------- 1 | .Footer { 2 | } 3 | -------------------------------------------------------------------------------- /Ch4/exercise-4-1/src/layout/Footer/Footer.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { shallow } from 'enzyme' 3 | import Footer from './Footer' 4 | 5 | describe('