├── Chapter03 ├── 1-react-hooks │ ├── .eslintcache │ ├── .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.test.tsx │ │ ├── App.tsx │ │ ├── Counter.tsx │ │ ├── Issues.tsx │ │ ├── Issues2.tsx │ │ ├── index.css │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock ├── 2-todo │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── List.tsx │ │ ├── Task.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock └── 3-reducer │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.tsx │ ├── Notes.tsx │ ├── index.tsx │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── Chapter04 ├── geolocation │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ ├── Geolocation.tsx │ │ │ └── GeolocationContainer.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock └── hocs │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.tsx │ ├── components │ │ └── MyComponent │ │ │ ├── WithInnerWidth.tsx │ │ │ └── index.tsx │ ├── index.tsx │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── Chapter05 └── graphql │ ├── .editorconfig │ ├── .eslintrc │ ├── .gitignore │ ├── .nvmrc │ ├── .prettierrc │ ├── .vscode │ └── settings.json │ ├── backend │ ├── .env.example │ ├── .eslintignore │ ├── config │ │ ├── config.json │ │ └── index.ts │ ├── global.d.ts │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── graphql │ │ │ ├── resolvers │ │ │ │ ├── index.ts │ │ │ │ └── user.ts │ │ │ └── types │ │ │ │ ├── Scalar.graphql │ │ │ │ ├── User.graphql │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── lib │ │ │ ├── auth.ts │ │ │ └── jwt.ts │ │ ├── models │ │ │ ├── User.ts │ │ │ └── index.ts │ │ └── types │ │ │ ├── index.ts │ │ │ ├── interfaces.ts │ │ │ └── types.ts │ └── tsconfig.json │ └── frontend │ ├── .babelrc │ ├── .eslintignore │ ├── .eslintrc │ ├── .gitignore │ ├── .ncurc.json │ ├── .prettierrc │ ├── global.d.ts │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── AppRoutes.tsx │ ├── components │ │ ├── dashboard │ │ │ ├── Dashboard.tsx │ │ │ └── DashboardLayout.tsx │ │ └── users │ │ │ ├── Login.styled.ts │ │ │ ├── Login.tsx │ │ │ └── LoginLayout.tsx │ ├── config │ │ ├── common.json │ │ ├── index.ts │ │ ├── local.json │ │ └── production.json │ ├── contexts │ │ └── user.tsx │ ├── graphql │ │ └── user │ │ │ ├── getUserData.query.ts │ │ │ └── login.mutation.ts │ ├── index.html │ ├── index.tsx │ ├── lib │ │ ├── jwt.ts │ │ └── middlewares │ │ │ └── user.ts │ ├── pages │ │ ├── dashboard.tsx │ │ ├── error404.tsx │ │ ├── home.tsx │ │ └── login.tsx │ ├── server.ts │ └── types │ │ ├── index.ts │ │ ├── interfaces.ts │ │ └── types.ts │ ├── tsconfig.json │ └── webpack.config.ts ├── Chapter06 ├── context-api │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── components │ │ │ ├── App.css │ │ │ ├── App.tsx │ │ │ └── Issues.tsx │ │ ├── contexts │ │ │ └── Issue.tsx │ │ ├── index.css │ │ ├── index.tsx │ │ ├── logo.svg │ │ ├── react-app-env.d.ts │ │ ├── reportWebVitals.ts │ │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock └── react-suspense-with-swr │ ├── .env │ ├── .eslintcache │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ ├── pokeball.png │ └── robots.txt │ ├── src │ ├── components │ │ ├── App.tsx │ │ └── Pokemon │ │ │ ├── LoadingSkeleton.tsx │ │ │ ├── PokeContainer.tsx │ │ │ ├── Pokedex.tsx │ │ │ ├── Pokemon.styled.ts │ │ │ ├── Pokemon.tsx │ │ │ └── fetcher.ts │ ├── index.css │ ├── index.tsx │ ├── logo.svg │ ├── react-app-env.d.ts │ ├── reportWebVitals.ts │ └── setupTests.ts │ ├── tsconfig.json │ └── yarn.lock ├── Chapter07 ├── animations │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Transition │ │ │ │ ├── Transition.css │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── controlled-components │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Controlled │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── event-switch │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Button │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── react-motion │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Transition │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── refs │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Focus │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── svg │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Circles │ │ │ │ ├── Circle.tsx │ │ │ │ └── RedCircle.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock └── uncontrolled-components │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.tsx │ ├── components │ │ └── Uncontrolled │ │ │ └── index.tsx │ ├── index.tsx │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── Chapter08 ├── css-modules │ ├── .babelrc │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── declarations.d.ts │ │ ├── index.css │ │ ├── index.html │ │ └── index.tsx │ ├── tsconfig.json │ └── webpack.config.js ├── inline-styles │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── FontSize │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── radium │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Button │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock └── styled-components │ ├── .babelrc │ ├── .gitignore │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── components │ │ └── Button │ │ │ └── index.tsx │ ├── index.html │ └── index.tsx │ ├── tsconfig.json │ └── webpack.config.js ├── Chapter09 ├── data-fetching │ ├── .babelrc │ ├── .gitignore │ ├── dist │ │ ├── public │ │ │ └── bundle.js │ │ └── server.js │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── App.tsx │ │ ├── client.tsx │ │ ├── declarations.d.ts │ │ ├── server.tsx │ │ └── template.ts │ ├── tsconfig.json │ └── webpack.config.js ├── next │ ├── .gitignore │ ├── next-env.d.ts │ ├── package-lock.json │ ├── package.json │ ├── pages │ │ └── index.tsx │ └── tsconfig.json └── server-side-rendering │ ├── .babelrc │ ├── .gitignore │ ├── dist │ ├── public │ │ └── bundle.js │ └── server.js │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── App.tsx │ ├── client.tsx │ ├── declarations.d.ts │ ├── server.tsx │ └── template.ts │ ├── tsconfig.json │ └── webpack.config.js ├── Chapter10 └── keys │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.tsx │ ├── components │ │ └── List │ │ │ └── index.tsx │ ├── index.tsx │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── Chapter11 ├── events │ ├── .babelrc │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── jest.config.js │ ├── package-lock.json │ ├── package.json │ ├── setUpTests.ts │ ├── src │ │ ├── components │ │ │ ├── App.tsx │ │ │ └── ShowInformation │ │ │ │ ├── index.test.tsx │ │ │ │ └── index.tsx │ │ ├── index.html │ │ └── index.tsx │ ├── tsconfig.json │ └── webpack.config.js └── testing │ ├── .babelrc │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── jest.config.js │ ├── package-lock.json │ ├── package.json │ ├── setUpTests.ts │ ├── src │ ├── components │ │ ├── App.tsx │ │ └── Hello │ │ │ ├── index.test.tsx │ │ │ └── index.tsx │ ├── index.html │ └── index.tsx │ ├── tsconfig.json │ └── webpack.config.js ├── Chapter12 ├── react-router-with-params │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.css │ │ ├── App.tsx │ │ ├── components │ │ │ ├── About │ │ │ │ └── index.tsx │ │ │ ├── Contact │ │ │ │ └── index.tsx │ │ │ ├── Contacts │ │ │ │ ├── Contacts.css │ │ │ │ └── index.tsx │ │ │ ├── Error404 │ │ │ │ └── index.tsx │ │ │ └── Home │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ ├── react-app-env.d.ts │ │ └── routes.tsx │ ├── tsconfig.json │ └── yarn.lock └── react-router │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.css │ ├── App.tsx │ ├── components │ │ ├── About.tsx │ │ ├── Contact.tsx │ │ ├── Error404.tsx │ │ └── Home.tsx │ ├── index.tsx │ ├── react-app-env.d.ts │ └── routes.tsx │ ├── tsconfig.json │ └── yarn.lock ├── Chapter13 ├── counter │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ ├── index.html │ │ ├── logo192.png │ │ ├── logo512.png │ │ ├── manifest.json │ │ └── robots.txt │ ├── src │ │ ├── App.tsx │ │ ├── components │ │ │ └── Counter │ │ │ │ └── index.tsx │ │ ├── index.tsx │ │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock └── keys │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ ├── src │ ├── App.tsx │ ├── components │ │ └── List │ │ │ └── index.tsx │ ├── index.tsx │ └── react-app-env.d.ts │ ├── tsconfig.json │ └── yarn.lock ├── LICENSE └── README.md /Chapter03/1-react-hooks/.eslintcache: -------------------------------------------------------------------------------- 1 | [{"/Users/czantany/projects/react-examples/src/App.tsx":"1","/Users/czantany/projects/react-examples/src/index.tsx":"2","/Users/czantany/projects/react-examples/src/Issues.tsx":"3"},{"size":146,"mtime":1609746693736,"results":"4","hashOfConfig":"5"},{"size":500,"mtime":1609706907049,"results":"6","hashOfConfig":"5"},{"size":1020,"mtime":1609745387645,"results":"7","hashOfConfig":"5"},{"filePath":"8","messages":"9","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"1thj8j1",{"filePath":"10","messages":"11","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"12","messages":"13","errorCount":0,"warningCount":1,"fixableErrorCount":0,"fixableWarningCount":0,"source":null},"/Users/czantany/projects/react-examples/src/App.tsx",["14"],"/Users/czantany/projects/react-examples/src/index.tsx",[],"/Users/czantany/projects/react-examples/src/Issues.tsx",["15"],{"ruleId":"16","severity":1,"message":"17","line":1,"column":17,"nodeType":"18","messageId":"19","endLine":1,"endColumn":25},{"ruleId":"20","severity":1,"message":"21","line":44,"column":87,"nodeType":"22","endLine":44,"endColumn":102},"@typescript-eslint/no-unused-vars","'useState' is defined but never used.","Identifier","unusedVar","react/jsx-no-target-blank","Using target=\"_blank\" without rel=\"noreferrer\" is a security risk: see https://html.spec.whatwg.org/multipage/links.html#link-type-noopener","JSXAttribute"] -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/.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 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-examples", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^16.14.2", 12 | "@types/react-dom": "^16.9.8", 13 | "axios": "^0.21.1", 14 | "react": "^17.0.1", 15 | "react-dom": "^17.0.1", 16 | "react-scripts": "4.0.1", 17 | "typescript": "^4.0.3", 18 | "web-vitals": "^0.2.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 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/1-react-hooks/public/favicon.ico -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/1-react-hooks/public/logo192.png -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/1-react-hooks/public/logo512.png -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/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 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/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 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/App.test.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render, screen } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | render(); 7 | const linkElement = screen.getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | import Issues2 from './Issues' 3 | 4 | const App = () => { 5 | return ( 6 | 7 | ) 8 | } 9 | 10 | export default App; 11 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/Counter.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | const Counter = () => { 4 | const [counter, setCounter] = useState(0) 5 | 6 | const handleCounter = (operation = 'add') => { 7 | if (operation === 'add') { 8 | return setCounter(counter + 1) 9 | } 10 | 11 | return setCounter(counter - 1) 12 | } 13 | 14 | return ( 15 |

16 | Counter: {counter}
17 | 18 | 19 |

20 | ) 21 | } 22 | export default Counter; 23 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/Issues.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import React, { Component } from 'react' 3 | import axios from 'axios' 4 | 5 | // Types 6 | type Issue = { 7 | number: number 8 | title: string 9 | url: string 10 | state: string 11 | } 12 | type Props = {} 13 | type State = { issues: Issue[] }; 14 | 15 | class Issues extends Component { 16 | constructor(props: any) { 17 | super(props) 18 | 19 | this.state = { 20 | issues: [] 21 | } 22 | } 23 | 24 | componentDidMount() { 25 | axios 26 | .get('https://api.github.com/repos/ContentPI/ContentPI/issues') 27 | .then((response: any) => { 28 | this.setState({ 29 | issues: response.data 30 | }) 31 | }) 32 | } 33 | 34 | render() { 35 | const { issues = [] } = this.state 36 | 37 | return ( 38 | <> 39 |

ContentPI Issues

40 | 41 | {issues.map((issue: Issue) => ( 42 |

43 | #{issue.number} {' '} 44 | {issue.title} {' '} 45 | {issue.state} 46 |

47 | ))} 48 | 49 | ) 50 | } 51 | } 52 | 53 | export default Issues -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/Issues2.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import React, { FC, useState, useEffect } from 'react' 3 | import axios from 'axios' 4 | 5 | // Types 6 | type Issue = { 7 | number: number 8 | title: string 9 | url: string 10 | state: string 11 | } 12 | 13 | const Issues: FC = () => { 14 | // The useState hook replace this.setState 15 | const [issues, setIssues] = useState([]) 16 | 17 | // When we use the useEffect hook with an empty array [] on the deps (second parameter) 18 | // this represents the componentDidMount method (will be executed when the component is mounted). 19 | useEffect(() => { 20 | axios 21 | .get('https://api.github.com/repos/ContentPI/ContentPI/issues') 22 | .then((response: any) => { 23 | // Here we update directly our issue state 24 | setIssues(response.data) 25 | }) 26 | }, []) 27 | 28 | return ( 29 | <> 30 |

ContentPI Issues

31 | 32 | {issues.map((issue: Issue) => ( 33 |

34 | #{issue.number} {' '} 35 | {issue.title} {' '} 36 | {issue.state} 37 |

38 | ))} 39 | 40 | ) 41 | } 42 | 43 | export default Issues -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/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 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/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 reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/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'; 6 | -------------------------------------------------------------------------------- /Chapter03/1-react-hooks/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter03/2-todo/.eslintcache: -------------------------------------------------------------------------------- 1 | [{"/Users/czantany/projects/hooks/src/App.tsx":"1","/Users/czantany/projects/hooks/src/index.tsx":"2","/Users/czantany/projects/hooks/src/List.tsx":"3","/Users/czantany/projects/hooks/src/Task.tsx":"4"},{"size":1594,"mtime":1611134783730,"results":"5","hashOfConfig":"6"},{"size":148,"mtime":1611115692706,"results":"7","hashOfConfig":"6"},{"size":653,"mtime":1611134149100,"results":"8","hashOfConfig":"6"},{"size":367,"mtime":1611134153320,"results":"9","hashOfConfig":"6"},{"filePath":"10","messages":"11","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"11s1i83",{"filePath":"12","messages":"13","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"14","messages":"15","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},{"filePath":"16","messages":"17","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"/Users/czantany/projects/hooks/src/App.tsx",[],"/Users/czantany/projects/hooks/src/index.tsx",[],"/Users/czantany/projects/hooks/src/List.tsx",[],"/Users/czantany/projects/hooks/src/Task.tsx",[]] -------------------------------------------------------------------------------- /Chapter03/2-todo/.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 | -------------------------------------------------------------------------------- /Chapter03/2-todo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hooks", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^16.9.53", 12 | "@types/react-dom": "^16.9.8", 13 | "@types/styled-components": "^5.1.7", 14 | "react": "^17.0.1", 15 | "react-dom": "^17.0.1", 16 | "react-scripts": "4.0.1", 17 | "styled-components": "^5.2.1", 18 | "typescript": "^4.0.3", 19 | "web-vitals": "^0.2.4" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter03/2-todo/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/2-todo/public/favicon.ico -------------------------------------------------------------------------------- /Chapter03/2-todo/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/2-todo/public/logo192.png -------------------------------------------------------------------------------- /Chapter03/2-todo/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/2-todo/public/logo512.png -------------------------------------------------------------------------------- /Chapter03/2-todo/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 | -------------------------------------------------------------------------------- /Chapter03/2-todo/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter03/2-todo/src/List.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import React, { FC, useEffect, memo } from 'react' 3 | 4 | // Components 5 | import Task from './Task' 6 | 7 | // Types 8 | export type Todo = { 9 | id: number 10 | task: string 11 | } 12 | 13 | interface Props { 14 | todoList: Todo[] 15 | handleDelete: any 16 | } 17 | 18 | const List: FC = ({ todoList, handleDelete }) => { 19 | useEffect(() => { 20 | // This effect is executed every new render 21 | // console.log('Rendering ') 22 | }) 23 | 24 | return ( 25 |
    26 | {todoList.map((todo: Todo) => ( 27 | 33 | ))} 34 |
35 | ) 36 | } 37 | 38 | export default memo(List) -------------------------------------------------------------------------------- /Chapter03/2-todo/src/Task.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC, useEffect, memo } from 'react' 2 | 3 | interface Props { 4 | id: number 5 | task: string 6 | handleDelete: any 7 | } 8 | 9 | const Task: FC = ({ id, task, handleDelete }) => { 10 | useEffect(() => { 11 | // console.log('Rendering ', task) 12 | }) 13 | 14 | return ( 15 |
  • {task}
  • 16 | ) 17 | } 18 | 19 | export default memo(Task) -------------------------------------------------------------------------------- /Chapter03/2-todo/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, 6 | document.getElementById('root') 7 | ); -------------------------------------------------------------------------------- /Chapter03/2-todo/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter03/2-todo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/.eslintcache: -------------------------------------------------------------------------------- 1 | [{"/Users/czantany/projects/reducer/src/Notes.tsx":"1"},{"size":1991,"mtime":1611216202187,"results":"2","hashOfConfig":"3"},{"filePath":"4","messages":"5","errorCount":0,"warningCount":0,"fixableErrorCount":0,"fixableWarningCount":0},"1vngkre","/Users/czantany/projects/reducer/src/Notes.tsx",[]] -------------------------------------------------------------------------------- /Chapter03/3-reducer/.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 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "reducer", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^16.9.53", 12 | "@types/react-dom": "^16.9.8", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.1", 16 | "typescript": "^4.0.3", 17 | "web-vitals": "^0.2.4" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/3-reducer/public/favicon.ico -------------------------------------------------------------------------------- /Chapter03/3-reducer/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/3-reducer/public/logo192.png -------------------------------------------------------------------------------- /Chapter03/3-reducer/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter03/3-reducer/public/logo512.png -------------------------------------------------------------------------------- /Chapter03/3-reducer/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 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Notes from './Notes' 2 | 3 | function App() { 4 | return ( 5 | 6 | ) 7 | } 8 | 9 | export default App 10 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import App from './App' 4 | 5 | ReactDOM.render(, document.getElementById('root')) -------------------------------------------------------------------------------- /Chapter03/3-reducer/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter03/3-reducer/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter04/geolocation/.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 | -------------------------------------------------------------------------------- /Chapter04/geolocation/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geolocation", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter04/geolocation/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter04/geolocation/public/favicon.ico -------------------------------------------------------------------------------- /Chapter04/geolocation/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter04/geolocation/public/logo192.png -------------------------------------------------------------------------------- /Chapter04/geolocation/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter04/geolocation/public/logo512.png -------------------------------------------------------------------------------- /Chapter04/geolocation/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 | -------------------------------------------------------------------------------- /Chapter04/geolocation/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter04/geolocation/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import GeolocationContainer from './components/GeolocationContainer' 3 | 4 | function App() { 5 | return ( 6 |
    7 | 8 |
    9 | ); 10 | } 11 | 12 | export default App; 13 | -------------------------------------------------------------------------------- /Chapter04/geolocation/src/components/Geolocation.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | 3 | type Props = { 4 | latitude: number | null 5 | longitude: number | null 6 | } 7 | 8 | const Geolocation: FC = ({ latitude, longitude }) => ( 9 |
    10 |

    Geolocation:

    11 |
    Latitude: {latitude}
    12 |
    Longitude: {longitude}
    13 |
    14 | ) 15 | 16 | export default Geolocation 17 | -------------------------------------------------------------------------------- /Chapter04/geolocation/src/components/GeolocationContainer.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react' 2 | import Geolocation from './Geolocation' 3 | 4 | const GeolocationContainer = () => { 5 | const [latitude, setLatitude] = useState(null) 6 | const [longitude, setLongitude] = useState(null) 7 | 8 | const handleSuccess = ({ coords: { latitude, longitude } }: { coords: { latitude: number; longitude: number }}) => { 9 | setLatitude(latitude) 10 | setLongitude(longitude) 11 | } 12 | 13 | useEffect(() => { 14 | if (navigator.geolocation) { 15 | navigator.geolocation.getCurrentPosition(handleSuccess) 16 | } 17 | }, []) 18 | 19 | 20 | return ( 21 | 22 | ) 23 | } 24 | 25 | export default GeolocationContainer -------------------------------------------------------------------------------- /Chapter04/geolocation/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /Chapter04/geolocation/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter04/geolocation/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter04/hocs/.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 | -------------------------------------------------------------------------------- /Chapter04/hocs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter04/hocs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter04/hocs/public/favicon.ico -------------------------------------------------------------------------------- /Chapter04/hocs/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter04/hocs/public/logo192.png -------------------------------------------------------------------------------- /Chapter04/hocs/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter04/hocs/public/logo512.png -------------------------------------------------------------------------------- /Chapter04/hocs/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 | -------------------------------------------------------------------------------- /Chapter04/hocs/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter04/hocs/src/App.tsx: -------------------------------------------------------------------------------- 1 | import MyComponent from './components/MyComponent' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter04/hocs/src/components/MyComponent/WithInnerWidth.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react' 2 | 3 | const withInnerWidth = (Component: any) => (props: any) => { 4 | const [innerWidth, setInnerWidth] = useState(window.innerWidth) 5 | 6 | const handleResize = () => { 7 | setInnerWidth(window.innerWidth) 8 | } 9 | 10 | useEffect(() => { 11 | window.addEventListener('resize', handleResize) 12 | 13 | return () => { // <<< This emulates the componentWillUnmount 14 | window.removeEventListener('resize', handleResize) 15 | } 16 | }, []) // <<< This emulates the componentDidMount 17 | 18 | return 19 | } 20 | 21 | export default withInnerWidth -------------------------------------------------------------------------------- /Chapter04/hocs/src/components/MyComponent/index.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import withInnerWidth from './WithInnerWidth' 3 | 4 | type Props = { 5 | innerWidth: number 6 | } 7 | 8 | const MyComponent: FC = ({ innerWidth }) =>
    innerWidth: {innerWidth}
    9 | 10 | 11 | export default withInnerWidth(MyComponent) -------------------------------------------------------------------------------- /Chapter04/hocs/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter04/hocs/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter04/hocs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter05/graphql/.editorconfig: -------------------------------------------------------------------------------- 1 | 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /Chapter05/graphql/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .DS_Store 4 | .env 5 | -------------------------------------------------------------------------------- /Chapter05/graphql/.nvmrc: -------------------------------------------------------------------------------- 1 | v15.8.0 2 | -------------------------------------------------------------------------------- /Chapter05/graphql/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "jsxSingleQuote": false, 5 | "printWidth": 80, 6 | "quoteProps": "as-needed", 7 | "semi": false, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "none", 11 | "useTabs": false 12 | } 13 | -------------------------------------------------------------------------------- /Chapter05/graphql/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": true, 3 | "eslint.workingDirectories": [ 4 | "./backend", 5 | "./frontend" 6 | ], 7 | "editor.defaultFormatter": "esbenp.prettier-vscode", 8 | "editor.formatOnSave": true, 9 | "typescript.tsdk": "node_modules/typescript/lib" 10 | } 11 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/.env.example: -------------------------------------------------------------------------------- 1 | DB_DIALECT=postgres 2 | DB_PORT=5432 3 | DB_HOST=localhost 4 | DB_DATABASE= 5 | DB_USERNAME= 6 | DB_PASSWORD= 7 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist/** 2 | /node_modules/** 3 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "port": 5000 4 | }, 5 | "security": { 6 | "secretKey": "C0nt3ntP1", 7 | "expiresIn": "7d" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/config/index.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import dotenv from 'dotenv' 3 | 4 | // Configuration 5 | import config from './config.json' 6 | 7 | // Loading .env vars 8 | dotenv.config() 9 | 10 | // Types 11 | type Db = { 12 | dialect: string 13 | host: string 14 | port: string 15 | database: string 16 | username: string 17 | password: string 18 | } 19 | 20 | type Security = { 21 | secretKey: string 22 | expiresIn: string 23 | } 24 | 25 | type Server = { 26 | port: number 27 | } 28 | 29 | // Extracting data from .env file 30 | const { 31 | DB_DIALECT = '', 32 | DB_PORT = '', 33 | DB_HOST = '', 34 | DB_DATABASE = '', 35 | DB_USERNAME = '', 36 | DB_PASSWORD = '', 37 | } = process.env 38 | 39 | const db: Db = { 40 | dialect: DB_DIALECT, 41 | port: DB_PORT, 42 | host: DB_HOST, 43 | database: DB_DATABASE, 44 | username: DB_USERNAME, 45 | password: DB_PASSWORD 46 | } 47 | 48 | // Configuration 49 | const { security, server } = config 50 | 51 | export const $db: Db = db 52 | export const $security: Security = security 53 | export const $server: Server = server 54 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.json' { 2 | const value: any 3 | export default value 4 | } 5 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/graphql/resolvers/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { loadFilesSync } from '@graphql-tools/load-files' 3 | import { mergeResolvers } from '@graphql-tools/merge' 4 | 5 | const resolversArray = loadFilesSync(path.join(__dirname, './')) 6 | const resolvers = mergeResolvers(resolversArray) 7 | 8 | export default resolvers 9 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/graphql/types/Scalar.graphql: -------------------------------------------------------------------------------- 1 | scalar UUID 2 | scalar Datetime 3 | scalar JSON 4 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/graphql/types/User.graphql: -------------------------------------------------------------------------------- 1 | type User { 2 | id: UUID! 3 | username: String! 4 | password: String! 5 | email: String! 6 | privilege: String! 7 | active: Boolean! 8 | createdAt: Datetime! 9 | updatedAt: Datetime! 10 | } 11 | 12 | type Query { 13 | getUsers: [User!] 14 | getUserData(at: String!): User! 15 | } 16 | 17 | type Mutation { 18 | createUser(input: CreateUserInput): User! 19 | login(input: LoginInput): AuthPayload! 20 | } 21 | 22 | input CreateUserInput { 23 | username: String! 24 | password: String! 25 | email: String! 26 | privilege: String! 27 | active: Boolean! 28 | } 29 | 30 | input LoginInput { 31 | email: String! 32 | password: String! 33 | } 34 | 35 | type AuthPayload { 36 | token: String! 37 | } 38 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/graphql/types/index.ts: -------------------------------------------------------------------------------- 1 | import path from 'path' 2 | import { loadFilesSync } from '@graphql-tools/load-files' 3 | import { mergeTypeDefs } from '@graphql-tools/merge' 4 | 5 | const typesArray = loadFilesSync(path.join(__dirname, './'), { extensions: ['graphql'] }) 6 | 7 | export default mergeTypeDefs(typesArray) 8 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/index.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { ApolloServer, makeExecutableSchema } from 'apollo-server' 3 | 4 | // Models 5 | import models from './models' 6 | 7 | // Type Definitions & Resolvers 8 | import resolvers from './graphql/resolvers' 9 | import typeDefs from './graphql/types' 10 | 11 | // Configuration 12 | import { $server } from '../config' 13 | 14 | // Schema 15 | const schema = makeExecutableSchema({ 16 | typeDefs, 17 | resolvers 18 | }) 19 | 20 | // Apollo Server 21 | const apolloServer = new ApolloServer({ 22 | schema, 23 | context: { 24 | models 25 | } 26 | }) 27 | 28 | const alter = true 29 | const force = false 30 | 31 | models.sequelize.sync({ alter, force }).then(() => { 32 | apolloServer 33 | .listen($server.port) 34 | .then(({ url }) => { 35 | // eslint-disable-next-line no-console 36 | console.log(`Running on ${url}`) 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/models/index.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { Sequelize } from 'sequelize' 3 | 4 | // Configuration 5 | import { $db } from '../../config' 6 | 7 | // Interfaces 8 | import { IModels } from '../types' 9 | 10 | // Db Connection 11 | const { dialect, port, host, database, username, password } = $db 12 | 13 | // Connecting to the database 14 | const uri = `${dialect}://${username}:${password}@${host}:${port}/${database}` 15 | const sequelize = new Sequelize(uri) 16 | 17 | // Models 18 | const models: IModels = { 19 | User: require('./User').default(sequelize, Sequelize), 20 | sequelize 21 | } 22 | 23 | export default models 24 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './interfaces' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/types/interfaces.ts: -------------------------------------------------------------------------------- 1 | // Types 2 | import { User, Sequelize } from './types' 3 | 4 | // Sequelize 5 | export interface IDataTypes { 6 | UUID: string 7 | UUIDV4(): string 8 | STRING: string 9 | BOOLEAN: boolean 10 | TEXT: string 11 | INTEGER: number 12 | DATE: string 13 | FLOAT: number 14 | } 15 | 16 | // User 17 | export interface IUser extends User, Sequelize { 18 | id: string 19 | token?: string 20 | createdAt?: Date 21 | updatedAt?: Date 22 | } 23 | 24 | export interface ICreateUserInput extends User {} 25 | 26 | export interface ILoginInput { 27 | email: string 28 | password: string 29 | } 30 | 31 | export interface IAuthPayload { 32 | token: string 33 | } 34 | 35 | // Models 36 | export interface IModels { 37 | User: any 38 | sequelize: any 39 | } 40 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/src/types/types.ts: -------------------------------------------------------------------------------- 1 | export type User = { 2 | username: string 3 | password: string 4 | email: string 5 | privilege: string 6 | active: boolean 7 | } 8 | 9 | export type Sequelize = { 10 | _defaults?: any 11 | name?: string 12 | options?: any 13 | associate?: any 14 | } 15 | -------------------------------------------------------------------------------- /Chapter05/graphql/backend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "./src", 4 | "esModuleInterop": true, 5 | "module": "commonjs", 6 | "noImplicitAny": true, 7 | "outDir": "dist", 8 | "resolveJsonModule": true, 9 | "sourceMap": true, 10 | "target": "es6", 11 | "typeRoots": ["./src/@types", "./node_modules/@types"] 12 | }, 13 | "include": ["src/**/*.ts"], 14 | "exclude": ["node_modules"] 15 | } 16 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/.eslintignore: -------------------------------------------------------------------------------- 1 | /dist/** 2 | /node_modules/** 3 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules/ 10 | 11 | # Optional eslint cache 12 | .eslintcache 13 | 14 | # Yarn Integrity file 15 | .yarn-integrity 16 | 17 | # Build directory 18 | dist/ 19 | 20 | # Public 21 | .DS_Store 22 | 23 | # Test 24 | coverage 25 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/.ncurc.json: -------------------------------------------------------------------------------- 1 | { 2 | "upgrade": true, 3 | "reject": [] 4 | } 5 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "jsxSingleQuote": false, 5 | "printWidth": 80, 6 | "quoteProps": "as-needed", 7 | "semi": false, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "none", 11 | "useTabs": false 12 | } 13 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/global.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.json' { 2 | const value: any 3 | export default value 4 | } 5 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/AppRoutes.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { BrowserRouter as Router, Route, Switch } from 'react-router-dom' 3 | 4 | // Components 5 | import HomePage from './pages/home' 6 | import DashboardPage from './pages/dashboard' 7 | import LoginPage from './pages/login' 8 | import Error404 from './pages/error404' 9 | 10 | const AppRoutes = () => ( 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | 21 | export default AppRoutes 22 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/components/dashboard/Dashboard.tsx: -------------------------------------------------------------------------------- 1 | interface IProps { 2 | connectedUser: any 3 | } 4 | 5 | const Dashboard = ({ connectedUser }) => ( 6 |
    7 |

    Welcome, {connectedUser.username}!

    8 | 9 | 12 |
    13 | ) 14 | 15 | export default Dashboard 16 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/components/dashboard/DashboardLayout.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { FC, ReactElement, useContext } from 'react' 3 | 4 | // Contexts 5 | import { UserContext } from '../../contexts/user' 6 | 7 | // Components 8 | import Dashboard from './Dashboard' 9 | 10 | const Layout: FC = (): ReactElement => { 11 | const { connectedUser } = useContext(UserContext) 12 | 13 | if (connectedUser) { 14 | return ( 15 | 16 | ) 17 | } 18 | 19 | return
    20 | } 21 | 22 | export default Layout 23 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/components/users/LoginLayout.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { redirectTo } from '@contentpi/lib' 3 | import { FC, ReactElement, useContext, useEffect } from 'react' 4 | 5 | // Contexts 6 | import { UserContext } from '../../contexts/user' 7 | 8 | // Components 9 | import Login from './Login' 10 | 11 | // Interfaces 12 | interface IProps { 13 | currentUrl: string 14 | } 15 | 16 | const Layout: FC = ({ currentUrl }): ReactElement => { 17 | const { login } = useContext(UserContext) 18 | 19 | return ( 20 | 21 | ) 22 | } 23 | 24 | export default Layout 25 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/config/common.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": { 3 | "port": 3000 4 | }, 5 | "security": { 6 | "secretKey": "C0nt3ntP1", 7 | "expiresIn": "7d" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/config/index.ts: -------------------------------------------------------------------------------- 1 | // Configuration 2 | import common from './common.json' 3 | import local from './local.json' 4 | import production from './production.json' 5 | 6 | // Interface 7 | interface IConfig { 8 | baseUrl: string 9 | apiUrl: string 10 | server: { 11 | port: number 12 | } 13 | security: { 14 | secretKey: string 15 | expiresIn: string 16 | } 17 | } 18 | 19 | const { NODE_ENV = 'development' } = process.env 20 | 21 | // development => local 22 | let environment = 'local' 23 | 24 | if (NODE_ENV !== 'development') { 25 | environment = NODE_ENV 26 | } 27 | 28 | // Configurations by environment 29 | const config: IConfig = { 30 | ...common, 31 | ...(environment === 'local' ? local : production) 32 | } 33 | 34 | // Environments validations 35 | export const isLocal = () => environment === 'local' 36 | export const isProduction = () => environment === 'production' 37 | 38 | export default config 39 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/config/local.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:3000", 3 | "apiUrl": "http://localhost:5000/graphql" 4 | } 5 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/config/production.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:3000", 3 | "apiUrl": "http://localhost:5000/graphql" 4 | } 5 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/graphql/user/getUserData.query.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { gql } from '@apollo/client' 3 | 4 | export default gql` 5 | query getUserData($at: String!) { 6 | getUserData(at: $at) { 7 | id 8 | email 9 | username 10 | privilege 11 | active 12 | } 13 | } 14 | ` 15 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/graphql/user/login.mutation.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { gql } from '@apollo/client' 3 | 4 | export default gql` 5 | mutation login($email: String!, $password: String!) { 6 | login(input: { email: $email, password: $password }) { 7 | token 8 | } 9 | } 10 | ` 11 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Login System 8 | 9 | 10 | 11 |
    12 | 13 | 14 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import ReactDOM from 'react-dom' 3 | 4 | // Apollo 5 | import { ApolloProvider, ApolloClient, InMemoryCache } from '@apollo/client'; 6 | 7 | // Components 8 | import AppRoutes from './AppRoutes' 9 | 10 | // Config 11 | import config from './config' 12 | 13 | // Apollo Client configuration 14 | const client = new ApolloClient({ 15 | uri: config.apiUrl, 16 | cache: new InMemoryCache() 17 | }); 18 | 19 | ReactDOM.render( 20 | 21 | 22 | 23 | , document.querySelector('#root')) 24 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/lib/jwt.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import jwt from 'jsonwebtoken' 3 | import { getBase64 } from '@contentpi/lib' 4 | 5 | // Configuration 6 | import config from '../config' 7 | 8 | // Getting our secretKey 9 | const { 10 | security: { secretKey } 11 | } = config 12 | 13 | export function jwtVerify(accessToken: any, cb: any): void { 14 | // Validating our accessToken 15 | jwt.verify(accessToken, secretKey, (error: any, accessTokenData: any = {}) => { 16 | const { data: user } = accessTokenData 17 | 18 | // If we got an error or the user is not connected we return false 19 | if (error || !user) { 20 | return cb(false) 21 | } 22 | 23 | // Getting the user data 24 | const userData = getBase64(user) 25 | 26 | return cb(userData) 27 | }) 28 | } 29 | 30 | export async function getUserData(accessToken: any): Promise { 31 | // This is an async function to retrieve the user data from the jwtVerify function 32 | const UserPromise = new Promise(resolve => jwtVerify(accessToken, (user: any) => resolve(user))) 33 | 34 | const user = await UserPromise 35 | 36 | return user 37 | } 38 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/lib/middlewares/user.ts: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { Request, Response, NextFunction } from 'express' 3 | 4 | // Lib 5 | import { getUserData } from '../jwt' 6 | 7 | export const isConnected = (isLogged = true, privileges = ['user'], redirectTo = '/') => async ( 8 | req: Request, 9 | res: Response, 10 | next: NextFunction 11 | ): Promise => { 12 | // Getting the user information by passing our 'at' cookie 13 | const user = await getUserData(req.cookies.at) 14 | 15 | if (!user && !isLogged) { 16 | // This is to allow No connected users 17 | return next() 18 | } 19 | 20 | // Allowing just connected users and validating privileges... 21 | if (user && isLogged) { 22 | // If the user is connected and is god... 23 | if (privileges.includes('god') && user.privilege === 'god') { 24 | return next() 25 | } 26 | 27 | // If the user is conencted and is admin... 28 | if (privileges.includes('admin') && user.privilege === 'admin') { 29 | return next() 30 | } 31 | 32 | // If the user is connected but is not god or admin. 33 | res.redirect(redirectTo) 34 | } else { 35 | // If the user is not connected 36 | res.redirect(redirectTo) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/pages/dashboard.tsx: -------------------------------------------------------------------------------- 1 | // Components 2 | import DashboardLayout from '../components/dashboard/DashboardLayout' 3 | 4 | // Contexts 5 | import UserProvider from '../contexts/user' 6 | 7 | const Page = () => ( 8 | 9 | 10 | 11 | ) 12 | 13 | export default Page 14 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/pages/error404.tsx: -------------------------------------------------------------------------------- 1 | const Page = () => ( 2 |
    3 |

    Error404

    4 |
    5 | ) 6 | 7 | export default Page 8 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/pages/home.tsx: -------------------------------------------------------------------------------- 1 | const Page = () => ( 2 |
    3 |

    Home

    4 | 5 | 8 |
    9 | ) 10 | 11 | export default Page 12 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/pages/login.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { FC, ReactElement } from 'react' 3 | import { isBrowser } from '@contentpi/lib' 4 | 5 | // Contexts 6 | import UserProvider from '../contexts/user' 7 | 8 | // Components 9 | import LoginLayout from '../components/users/LoginLayout' 10 | 11 | interface IProps { 12 | currentUrl: string 13 | } 14 | 15 | const Page: FC = ({ 16 | currentUrl = isBrowser() ? window.location.search.replace('?redirectTo=', '') : '' 17 | }): ReactElement => ( 18 | 19 | 20 | 21 | ) 22 | 23 | export default Page 24 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from './interfaces' 2 | export * from './types' 3 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/types/interfaces.ts: -------------------------------------------------------------------------------- 1 | import { User } from './types' 2 | 3 | // User 4 | export interface IUser extends User { 5 | id?: string 6 | token?: string 7 | createdAt?: Date 8 | updatedAt?: Date 9 | } 10 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/src/types/types.ts: -------------------------------------------------------------------------------- 1 | export type User = { 2 | username?: string 3 | password: string 4 | email: string 5 | privilege?: string 6 | active?: boolean 7 | } 8 | -------------------------------------------------------------------------------- /Chapter05/graphql/frontend/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "target": "es5", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "module": "commonjs", 14 | "moduleResolution": "node", 15 | "resolveJsonModule": true, 16 | "isolatedModules": true, 17 | "noEmit": true, 18 | "jsx": "react-jsx", 19 | "noImplicitAny": false, 20 | "types": ["node", "express"] 21 | }, 22 | "include": ["src"] 23 | } 24 | -------------------------------------------------------------------------------- /Chapter06/context-api/.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 | -------------------------------------------------------------------------------- /Chapter06/context-api/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-examples", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/axios": "^0.14.0", 10 | "@types/jest": "^26.0.15", 11 | "@types/node": "^12.0.0", 12 | "@types/react": "^16.14.2", 13 | "@types/react-dom": "^16.9.8", 14 | "axios": "^0.21.1", 15 | "react": "^17.0.1", 16 | "react-dom": "^17.0.1", 17 | "react-scripts": "4.0.1", 18 | "typescript": "^4.0.3", 19 | "web-vitals": "^0.2.4" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter06/context-api/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/context-api/public/favicon.ico -------------------------------------------------------------------------------- /Chapter06/context-api/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/context-api/public/logo192.png -------------------------------------------------------------------------------- /Chapter06/context-api/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/context-api/public/logo512.png -------------------------------------------------------------------------------- /Chapter06/context-api/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 | -------------------------------------------------------------------------------- /Chapter06/context-api/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter06/context-api/src/components/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 | -------------------------------------------------------------------------------- /Chapter06/context-api/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | // Providers 2 | import IssueProvider from '../contexts/Issue' 3 | 4 | // Components 5 | import Issues from './Issues' 6 | 7 | const App = () => { 8 | return ( 9 | 10 | 11 | 12 | ) 13 | } 14 | 15 | export default App; 16 | -------------------------------------------------------------------------------- /Chapter06/context-api/src/components/Issues.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { FC, useContext } from 'react' 3 | 4 | // Contexts 5 | import { IssueContext, Issue } from '../contexts/Issue' 6 | 7 | const Issues: FC = () => { 8 | // Here you consume your Context, and you can grab the issues value. 9 | const { issues, url } = useContext(IssueContext) 10 | 11 | return ( 12 | <> 13 |

    ContentPI Issues from Context

    14 | 15 | {issues.map((issue: Issue) => ( 16 |

    17 | #{issue.number} {' '} 18 | {issue.title} {' '} 19 | {issue.state} 20 |

    21 | ))} 22 | 23 | ) 24 | } 25 | 26 | export default Issues -------------------------------------------------------------------------------- /Chapter06/context-api/src/contexts/Issue.tsx: -------------------------------------------------------------------------------- 1 | import { FC, createContext, useState, useEffect, ReactElement, useCallback } from 'react' 2 | import axios from 'axios' 3 | 4 | export type Issue = { 5 | number: number 6 | title: string 7 | url: string 8 | state: string 9 | } 10 | 11 | interface Issue_Context { 12 | issues: Issue[] 13 | url: string 14 | } 15 | 16 | interface Props { 17 | children: ReactElement 18 | url: string 19 | } 20 | 21 | export const IssueContext = createContext({ 22 | issues: [], 23 | url: '' 24 | }) 25 | 26 | const IssueProvider: FC = ({ children, url }): ReactElement => { 27 | // State 28 | const [issues, setIssues] = useState([]) 29 | 30 | const fetchIssues = useCallback(async () => { 31 | const response = await axios(url) 32 | 33 | if (response) { 34 | setIssues(response.data) 35 | } 36 | }, [url]) 37 | 38 | // Effects 39 | useEffect(() => { 40 | fetchIssues() 41 | }, [fetchIssues]) 42 | 43 | const context = { 44 | issues, 45 | url 46 | } 47 | 48 | return {children} 49 | } 50 | 51 | export default IssueProvider -------------------------------------------------------------------------------- /Chapter06/context-api/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 | -------------------------------------------------------------------------------- /Chapter06/context-api/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './components/App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /Chapter06/context-api/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter06/context-api/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /Chapter06/context-api/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'; 6 | -------------------------------------------------------------------------------- /Chapter06/context-api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/.env: -------------------------------------------------------------------------------- 1 | SKIP_PREFLIGHT_CHECK=true -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/.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 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-examples", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/axios": "^0.14.0", 10 | "@types/jest": "^26.0.15", 11 | "@types/node": "^12.0.0", 12 | "@types/react": "^16.14.2", 13 | "@types/react-dom": "^16.9.8", 14 | "@types/styled-components": "^5.1.9", 15 | "react": "17.0.1", 16 | "react-dom": "17.0.1", 17 | "react-loading-skeleton": "^2.2.0", 18 | "react-scripts": "4.0.1", 19 | "styled-components": "^5.2.1", 20 | "swr": "^0.5.4", 21 | "typescript": "^4.0.3", 22 | "web-vitals": "^0.2.4" 23 | }, 24 | "scripts": { 25 | "start": "react-scripts start", 26 | "build": "react-scripts build", 27 | "test": "react-scripts test", 28 | "eject": "react-scripts eject" 29 | }, 30 | "eslintConfig": { 31 | "extends": [ 32 | "react-app", 33 | "react-app/jest" 34 | ] 35 | }, 36 | "browserslist": { 37 | "production": [ 38 | ">0.2%", 39 | "not dead", 40 | "not op_mini all" 41 | ], 42 | "development": [ 43 | "last 1 chrome version", 44 | "last 1 firefox version", 45 | "last 1 safari version" 46 | ] 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/react-suspense-with-swr/public/favicon.ico -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/react-suspense-with-swr/public/logo192.png -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/react-suspense-with-swr/public/logo512.png -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/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 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/public/pokeball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter06/react-suspense-with-swr/public/pokeball.png -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { SWRConfig } from 'swr' 3 | 4 | // Components 5 | import PokeContainer from './Pokemon/PokeContainer' 6 | import fetcher from './Pokemon/fetcher' 7 | 8 | // Styles 9 | import { StyledPokedex, StyledTitle } from './Pokemon/Pokemon.styled' 10 | 11 | const App = () => { 12 | return ( 13 | <> 14 | Pokedex 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | ) 28 | } 29 | 30 | export default App 31 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/components/Pokemon/LoadingSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import Skeleton from 'react-loading-skeleton' 3 | 4 | const LoadingSkeleton: FC = () => ( 5 |
    6 | 7 |
    8 | ) 9 | 10 | export default LoadingSkeleton 11 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/components/Pokemon/PokeContainer.tsx: -------------------------------------------------------------------------------- 1 | import { FC, Suspense } from 'react' 2 | 3 | import Pokedex from './Pokedex' 4 | 5 | const PokeContainer: FC = () => { 6 | return ( 7 | Loading Pokedex...}> 8 | 9 | 10 | ) 11 | } 12 | 13 | export default PokeContainer -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/components/Pokemon/Pokedex.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { FC, Suspense } from 'react' 3 | import useSWR from 'swr' 4 | 5 | // Components 6 | import LoadingSkeleton from './LoadingSkeleton' 7 | import Pokemon from './Pokemon' 8 | 9 | import { StyledGrid } from './Pokemon.styled' 10 | 11 | const Pokedex: FC = () => { 12 | const { data: { results } } = useSWR('https://pokeapi.co/api/v2/pokemon?limit=150') 13 | 14 | return ( 15 | <> 16 | {results.map((pokemon: { name: string }) => ( 17 | }> 18 | 19 | 20 | ))} 21 | 22 | ) 23 | } 24 | 25 | export default Pokedex 26 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/components/Pokemon/Pokemon.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { FC } from 'react' 3 | import useSWR from 'swr' 4 | 5 | // Styles 6 | import { StyledCard, StyledTypes, StyledType, StyledHeader } from './Pokemon.styled' 7 | 8 | type Props = { 9 | pokemonName: string 10 | } 11 | 12 | const Pokemon: FC = ({ pokemonName }) => { 13 | const { data, error } = useSWR(`https://pokeapi.co/api/v2/pokemon/${pokemonName}`) 14 | 15 | // Do you remember the error we set on the fetcher? 16 | if (error || data.error) { 17 | return
    18 | } 19 | 20 | if (!data) { 21 | return
    Loading...
    22 | } 23 | 24 | const { id, name, sprites, types } = data 25 | const pokemonTypes = types.map((pokemonType: any) => pokemonType.type.name) 26 | 27 | return ( 28 | 29 | 30 |

    {name}

    31 |
    #{id}
    32 |
    33 | 34 | {name} 35 | 36 | 37 | {pokemonTypes.map((pokemonType: string) => {pokemonType})} 38 | 39 |
    40 | ) 41 | } 42 | 43 | export default Pokemon 44 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/components/Pokemon/fetcher.ts: -------------------------------------------------------------------------------- 1 | const fetcher = (url: string) => { 2 | return fetch(url).then((response) => { 3 | if (response.ok) { 4 | return response.json() 5 | } 6 | 7 | return { 8 | error: true 9 | } 10 | }) 11 | } 12 | 13 | export default fetcher 14 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/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 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './components/App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | // If you want to start measuring performance in your app, pass a function 10 | // to log results (for example: reportWebVitals(console.log)) 11 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 12 | reportWebVitals(); 13 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/src/reportWebVitals.ts: -------------------------------------------------------------------------------- 1 | import { ReportHandler } from 'web-vitals'; 2 | 3 | const reportWebVitals = (onPerfEntry?: ReportHandler) => { 4 | if (onPerfEntry && onPerfEntry instanceof Function) { 5 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 6 | getCLS(onPerfEntry); 7 | getFID(onPerfEntry); 8 | getFCP(onPerfEntry); 9 | getLCP(onPerfEntry); 10 | getTTFB(onPerfEntry); 11 | }); 12 | } 13 | }; 14 | 15 | export default reportWebVitals; 16 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/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'; 6 | -------------------------------------------------------------------------------- /Chapter06/react-suspense-with-swr/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/animations/.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 | -------------------------------------------------------------------------------- /Chapter07/animations/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-addons-css-transition-group": "^15.0.5", 13 | "@types/react-dom": "^17.0.0", 14 | "react": "^17.0.1", 15 | "react-addons-css-transition-group": "^15.6.2", 16 | "react-dom": "^17.0.1", 17 | "react-scripts": "4.0.2", 18 | "typescript": "^4.1.2", 19 | "web-vitals": "^1.0.1" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter07/animations/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/animations/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/animations/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/animations/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/animations/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/animations/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/animations/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 | -------------------------------------------------------------------------------- /Chapter07/animations/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/animations/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Transition from './components/Transition' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter07/animations/src/components/Transition/Transition.css: -------------------------------------------------------------------------------- 1 | .fade-enter { 2 | opacity: 0.01; 3 | } 4 | 5 | .fade-enter.fade-appear-active { 6 | opacity: 1; 7 | transition: opacity .5s ease-in; 8 | } -------------------------------------------------------------------------------- /Chapter07/animations/src/components/Transition/index.tsx: -------------------------------------------------------------------------------- 1 | import CSSTransitionGroup from 'react-addons-css-transition-group' 2 | import './Transition.css' 3 | 4 | const Transition = () => ( 5 | 10 |

    Hello React

    11 |
    12 | ) 13 | 14 | export default Transition -------------------------------------------------------------------------------- /Chapter07/animations/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/animations/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/animations/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/.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 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/controlled-components/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/controlled-components/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/controlled-components/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/controlled-components/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/controlled-components/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/controlled-components/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 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Controlled from './components/Controlled' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter07/controlled-components/src/components/Controlled/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | const Controlled = () => { 4 | const [values, setValues] = useState({ firstName: '', lastName: '' }) 5 | 6 | const handleChange = (e: any) => { 7 | const { target: { name, value } } = e 8 | 9 | setValues({ 10 | ...values, 11 | [name]: value 12 | }) 13 | } 14 | 15 | const handleSubmit = (e: any) => { 16 | e.preventDefault() 17 | 18 | console.log(`${values.firstName} ${values.lastName}`, values) 19 | } 20 | 21 | return ( 22 |
    23 | 29 | 35 | 36 |
    37 | ) 38 | } 39 | 40 | export default Controlled -------------------------------------------------------------------------------- /Chapter07/controlled-components/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/controlled-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/event-switch/.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 | -------------------------------------------------------------------------------- /Chapter07/event-switch/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter07/event-switch/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/event-switch/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/event-switch/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/event-switch/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/event-switch/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/event-switch/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/event-switch/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 | -------------------------------------------------------------------------------- /Chapter07/event-switch/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/event-switch/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Button from './components/Button' 2 | 3 | function App() { 4 | return ( 5 |
    6 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter07/event-switch/src/components/Button/index.tsx: -------------------------------------------------------------------------------- 1 | const Button = () => { 2 | const handleEvent = (event: any) => { 3 | switch (event.type) { 4 | case 'click': 5 | console.log('clicked') 6 | break 7 | 8 | case 'dblclick': 9 | console.log('double clicked') 10 | break 11 | 12 | default: 13 | console.log('unhandled', event.type) 14 | } 15 | } 16 | 17 | return ( 18 | 24 | ) 25 | } 26 | 27 | export default Button -------------------------------------------------------------------------------- /Chapter07/event-switch/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/event-switch/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/event-switch/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/react-motion/.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 | -------------------------------------------------------------------------------- /Chapter07/react-motion/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-addons-css-transition-group": "^15.0.5", 13 | "@types/react-dom": "^17.0.0", 14 | "@types/react-motion": "^0.0.29", 15 | "react": "^17.0.1", 16 | "react-addons-css-transition-group": "^15.6.2", 17 | "react-dom": "^17.0.1", 18 | "react-motion": "^0.5.2", 19 | "react-scripts": "4.0.2", 20 | "typescript": "^4.1.2", 21 | "web-vitals": "^1.0.1" 22 | }, 23 | "scripts": { 24 | "start": "react-scripts start", 25 | "build": "react-scripts build", 26 | "test": "react-scripts test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "react-app", 32 | "react-app/jest" 33 | ] 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.2%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 1 chrome version", 43 | "last 1 firefox version", 44 | "last 1 safari version" 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Chapter07/react-motion/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/react-motion/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/react-motion/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/react-motion/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/react-motion/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/react-motion/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/react-motion/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 | -------------------------------------------------------------------------------- /Chapter07/react-motion/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/react-motion/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Transition from './components/Transition' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter07/react-motion/src/components/Transition/index.tsx: -------------------------------------------------------------------------------- 1 | import { Motion, spring } from 'react-motion' 2 | 3 | const Transition = () => ( 4 | 8 | {interpolatingStyle => ( 9 |

    Hello React

    10 | )} 11 |
    12 | ) 13 | 14 | export default Transition -------------------------------------------------------------------------------- /Chapter07/react-motion/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/react-motion/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/react-motion/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/refs/.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 | -------------------------------------------------------------------------------- /Chapter07/refs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter07/refs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/refs/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/refs/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/refs/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/refs/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/refs/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/refs/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 | -------------------------------------------------------------------------------- /Chapter07/refs/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/refs/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Focus from './components/Focus' 2 | import Reset from './components/Input/Reset' 3 | 4 | function App() { 5 | return ( 6 |
    7 |
    8 | 9 |
    10 | ) 11 | } 12 | 13 | export default App -------------------------------------------------------------------------------- /Chapter07/refs/src/components/Focus/index.tsx: -------------------------------------------------------------------------------- 1 | import { useRef } from 'react' 2 | 3 | const Focus = () => { 4 | const inputRef = useRef(null) 5 | 6 | const handleClick = () => { 7 | inputRef.current.focus() 8 | } 9 | 10 | return ( 11 | <> 12 | 16 | 17 | 18 | ) 19 | } 20 | 21 | export default Focus -------------------------------------------------------------------------------- /Chapter07/refs/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/refs/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/refs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/svg/.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 | -------------------------------------------------------------------------------- /Chapter07/svg/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-addons-css-transition-group": "^15.0.5", 13 | "@types/react-dom": "^17.0.0", 14 | "@types/react-motion": "^0.0.29", 15 | "react": "^17.0.1", 16 | "react-addons-css-transition-group": "^15.6.2", 17 | "react-dom": "^17.0.1", 18 | "react-motion": "^0.5.2", 19 | "react-scripts": "4.0.2", 20 | "typescript": "^4.1.2", 21 | "web-vitals": "^1.0.1" 22 | }, 23 | "scripts": { 24 | "start": "react-scripts start", 25 | "build": "react-scripts build", 26 | "test": "react-scripts test", 27 | "eject": "react-scripts eject" 28 | }, 29 | "eslintConfig": { 30 | "extends": [ 31 | "react-app", 32 | "react-app/jest" 33 | ] 34 | }, 35 | "browserslist": { 36 | "production": [ 37 | ">0.2%", 38 | "not dead", 39 | "not op_mini all" 40 | ], 41 | "development": [ 42 | "last 1 chrome version", 43 | "last 1 firefox version", 44 | "last 1 safari version" 45 | ] 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Chapter07/svg/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/svg/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/svg/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/svg/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/svg/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/svg/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/svg/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 | -------------------------------------------------------------------------------- /Chapter07/svg/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/svg/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Circle from './components/Circles/Circle' 2 | import RedCircle from './components/Circles/RedCircle' 3 | 4 | function App() { 5 | return ( 6 |
    7 | 8 | 9 |
    10 | ) 11 | } 12 | 13 | export default App -------------------------------------------------------------------------------- /Chapter07/svg/src/components/Circles/Circle.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | 3 | type Props = { 4 | x: number 5 | y: number 6 | radius: number 7 | fill: string 8 | } 9 | 10 | const Circle: FC = ({ x, y, radius, fill }) => ( 11 | 12 | 13 | 14 | ) 15 | 16 | export default Circle -------------------------------------------------------------------------------- /Chapter07/svg/src/components/Circles/RedCircle.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | import Circle from './Circle' 3 | 4 | type Props = { 5 | x: number 6 | y: number 7 | radius: number 8 | } 9 | 10 | const RedCircle: FC = ({ x, y, radius }) => ( 11 | 12 | ); 13 | 14 | export default RedCircle -------------------------------------------------------------------------------- /Chapter07/svg/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/svg/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/svg/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/.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 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/uncontrolled-components/public/favicon.ico -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/uncontrolled-components/public/logo192.png -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter07/uncontrolled-components/public/logo512.png -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/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 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Uncontrolled from './components/Uncontrolled' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/src/components/Uncontrolled/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | const Uncontrolled = () => { 4 | const [values, setValues] = useState({ firstName: '', lastName: '' }) 5 | 6 | const handleChange = (e: any) => { 7 | const { target: { name, value } } = e 8 | 9 | setValues({ 10 | ...values, 11 | [name]: value 12 | }) 13 | } 14 | 15 | const handleSubmit = (e: any) => { 16 | e.preventDefault() 17 | 18 | console.log(`${values.firstName} ${values.lastName}`, values) 19 | } 20 | 21 | return ( 22 |
    23 | 28 | 33 | 34 |
    35 | ) 36 | } 37 | 38 | export default Uncontrolled -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter07/uncontrolled-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter08/css-modules/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /Chapter08/css-modules/.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 | -------------------------------------------------------------------------------- /Chapter08/css-modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack serve --mode development --port 3000" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@babel/core": "^7.12.16", 13 | "@babel/preset-env": "^7.12.16", 14 | "@babel/preset-react": "^7.12.13", 15 | "css-loader": "^5.0.2", 16 | "fork-ts-checker-webpack-plugin": "^6.1.0", 17 | "html-webpack-plugin": "^5.1.0", 18 | "style-loader": "^2.0.0", 19 | "ts-loader": "^8.0.17", 20 | "typescript": "^4.1.5", 21 | "webpack": "^5.21.2", 22 | "webpack-cli": "^4.5.0", 23 | "webpack-dev-server": "^3.11.2" 24 | }, 25 | "dependencies": { 26 | "react": "^17.0.1", 27 | "react-css-modules": "^4.7.11", 28 | "react-dom": "^17.0.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter08/css-modules/src/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css' { 2 | const content: Record 3 | export default content 4 | } -------------------------------------------------------------------------------- /Chapter08/css-modules/src/index.css: -------------------------------------------------------------------------------- 1 | .button { 2 | background-color: #ff0000; 3 | width: 320px; 4 | padding: 20px; 5 | border-radius: 5px; 6 | border: none; 7 | outline: none; 8 | } -------------------------------------------------------------------------------- /Chapter08/css-modules/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | -------------------------------------------------------------------------------- /Chapter08/css-modules/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { render } from 'react-dom' 3 | import cssModules from 'react-css-modules' 4 | import styles from './index.css' 5 | 6 | // Components 7 | // onst Button = () => // This is for css modules 8 | const Button = () => // This is for React CSS modules 9 | 10 | const EnhancedButton = cssModules(Button, styles) 11 | 12 | // render(
    11 | ) 12 | } 13 | 14 | export default Radium(App) -------------------------------------------------------------------------------- /Chapter08/radium/src/components/Button/index.tsx: -------------------------------------------------------------------------------- 1 | import Radium from 'radium' 2 | 3 | const styles = { 4 | backgroundColor: '#ff0000', 5 | width: 320, 6 | padding: 20, 7 | borderRadius: 5, 8 | border: 'none', 9 | outline: 'none', 10 | ':hover': { 11 | color: '#fff', 12 | }, 13 | ':active': { 14 | position: 'relative', 15 | top: 2, 16 | }, 17 | '@media (max-width: 480px)': { 18 | width: 160, 19 | } 20 | }; 21 | 22 | const Button = () => ( 23 | 24 | ); 25 | 26 | export default Radium(Button) -------------------------------------------------------------------------------- /Chapter08/radium/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render(, document.getElementById('root')); 6 | -------------------------------------------------------------------------------- /Chapter08/radium/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter08/radium/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter08/styled-components/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /Chapter08/styled-components/.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 | -------------------------------------------------------------------------------- /Chapter08/styled-components/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "webpack serve --mode development --port 3000" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@babel/core": "^7.12.16", 13 | "@babel/preset-env": "^7.12.16", 14 | "@babel/preset-react": "^7.12.13", 15 | "css-loader": "^5.0.2", 16 | "fork-ts-checker-webpack-plugin": "^6.1.0", 17 | "html-webpack-plugin": "^5.1.0", 18 | "style-loader": "^2.0.0", 19 | "ts-loader": "^8.0.17", 20 | "typescript": "^4.1.5", 21 | "webpack": "^5.21.2", 22 | "webpack-cli": "^4.5.0", 23 | "webpack-dev-server": "^3.11.2" 24 | }, 25 | "dependencies": { 26 | "react": "^17.0.1", 27 | "react-dom": "^17.0.1", 28 | "styled-components": "^5.2.1" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Chapter08/styled-components/src/components/Button/index.tsx: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components' 2 | 3 | const Button = styled.button` 4 | background-color: #ff0000; 5 | width: 320px; 6 | padding: 20px; 7 | border-radius: 5px; 8 | border: none; 9 | outline: none; 10 | &:hover { 11 | color: #fff; 12 | } 13 | &:active { 14 | position: relative; 15 | top: 2px; 16 | } 17 | 18 | @media (max-width: 480px) { 19 | width: 160px; 20 | } 21 | ` 22 | 23 | export default Button -------------------------------------------------------------------------------- /Chapter08/styled-components/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | -------------------------------------------------------------------------------- /Chapter08/styled-components/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { render } from 'react-dom' 3 | import Button from './components/Button' 4 | 5 | render(, document.querySelector('#root')) -------------------------------------------------------------------------------- /Chapter08/styled-components/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "baseUrl": "src", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "isolatedModules": true, 9 | "jsx": "react-jsx", 10 | "lib": ["dom", "dom.iterable", "esnext"], 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noEmit": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitAny": false, 16 | "resolveJsonModule": true, 17 | "skipLibCheck": true, 18 | "sourceMap": true, 19 | "strict": true, 20 | "target": "es6" 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.tsx"], 23 | "exclude": ["node_modules"] 24 | } -------------------------------------------------------------------------------- /Chapter09/data-fetching/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /Chapter09/data-fetching/.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 | -------------------------------------------------------------------------------- /Chapter09/data-fetching/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node ./dist/server", 8 | "build": "webpack" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@babel/core": "^7.12.16", 14 | "@babel/preset-env": "^7.12.16", 15 | "@babel/preset-react": "^7.12.13", 16 | "@types/isomorphic-fetch": "^0.0.35", 17 | "css-loader": "^5.0.2", 18 | "fork-ts-checker-webpack-plugin": "^6.1.0", 19 | "html-webpack-plugin": "^5.1.0", 20 | "style-loader": "^2.0.0", 21 | "ts-loader": "^8.0.17", 22 | "typescript": "^4.1.5", 23 | "webpack": "^5.21.2", 24 | "webpack-cli": "^4.5.0", 25 | "webpack-dev-server": "^3.11.2", 26 | "webpack-node-externals": "^2.5.2" 27 | }, 28 | "dependencies": { 29 | "@types/express": "^4.17.11", 30 | "@types/react": "^17.0.2", 31 | "@types/react-dom": "^17.0.1", 32 | "express": "^4.17.1", 33 | "isomorphic-fetch": "^3.0.0", 34 | "react": "^17.0.1", 35 | "react-dom": "^17.0.1" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Chapter09/data-fetching/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { FC } from 'react' 2 | 3 | type Gist = { 4 | id: string 5 | description: string 6 | } 7 | 8 | type Props = { 9 | gists: Gist[] 10 | } 11 | 12 | const App: FC = ({ gists }) => ( 13 |
      14 | {gists.map(gist => ( 15 |
    • {gist.description}
    • 16 | ))} 17 |
    18 | ) 19 | 20 | export default App -------------------------------------------------------------------------------- /Chapter09/data-fetching/src/client.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom' 2 | import App from './App'; 3 | 4 | type Gist = { 5 | id: string 6 | description: string 7 | } 8 | 9 | declare global { 10 | interface Window { 11 | gists: Gist[] 12 | } 13 | } 14 | 15 | ReactDOM.hydrate(, document.getElementById('app')) -------------------------------------------------------------------------------- /Chapter09/data-fetching/src/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css' { 2 | const content: Record 3 | export default content 4 | } -------------------------------------------------------------------------------- /Chapter09/data-fetching/src/server.tsx: -------------------------------------------------------------------------------- 1 | import express, { Request, Response } from 'express' 2 | import React from 'react' 3 | import ReactDOM from 'react-dom/server' 4 | import path from 'path' 5 | import fetch from 'isomorphic-fetch' 6 | import App from './App' 7 | import template from './template' 8 | 9 | const app = express() 10 | 11 | app.use(express.static(path.resolve(__dirname, './dist/public'))) 12 | 13 | // @ts-expect-error 14 | app.get('/', (req: Request, res: Response) => { 15 | fetch('https://api.github.com/users/gaearon/gists') 16 | .then(response => response.json()) 17 | .then(gists => { 18 | const body = ReactDOM.renderToString() 19 | const html = template(body, gists) 20 | 21 | res.send(html) 22 | }) 23 | }) 24 | 25 | app.listen(3000, () => console.log('Listening on port 3000')) -------------------------------------------------------------------------------- /Chapter09/data-fetching/src/template.ts: -------------------------------------------------------------------------------- 1 | export default (body: any, gists: any) => ` 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    ${body}
    9 | 10 | 11 | 12 | 13 | ` -------------------------------------------------------------------------------- /Chapter09/data-fetching/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "baseUrl": "src", 5 | "allowSyntheticDefaultImports": true, 6 | "target": "es5", 7 | "module": "commonjs", 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "jsx": "react-jsx", 14 | "lib": ["dom", "dom.iterable", "esnext"], 15 | "strict": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "esModuleInterop": true 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.tsx"], 23 | "exclude": ["node_modules"] 24 | } -------------------------------------------------------------------------------- /Chapter09/data-fetching/webpack.config.js: -------------------------------------------------------------------------------- 1 | 2 | const nodeExternals = require('webpack-node-externals'); 3 | const path = require('path'); 4 | 5 | const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development'; 6 | 7 | const rules = [{ 8 | test: /\.(tsx|ts)$/, 9 | use: 'ts-loader', 10 | exclude: /node_modules/ 11 | }]; 12 | 13 | const client = { 14 | mode, 15 | entry: './src/client.tsx', 16 | output: { 17 | path: path.resolve(__dirname, './dist/public'), 18 | filename: 'bundle.js', 19 | publicPath: '/' 20 | }, 21 | module: { 22 | rules 23 | }, 24 | resolve: { 25 | extensions: [".ts", ".tsx", ".js", ".json"], 26 | }, 27 | }; 28 | 29 | const server = { 30 | mode, 31 | entry: './src/server.tsx', 32 | output: { 33 | path: path.resolve(__dirname, './dist'), 34 | filename: 'server.js', 35 | publicPath: '/' 36 | }, 37 | module: { 38 | rules 39 | }, 40 | target: 'node', 41 | externals: [nodeExternals()], 42 | resolve: { 43 | extensions: [".ts", ".tsx", ".js", ".json"], 44 | }, 45 | }; 46 | 47 | module.exports = [client, server]; -------------------------------------------------------------------------------- /Chapter09/next/.gitignore: -------------------------------------------------------------------------------- 1 | .next 2 | node_modules -------------------------------------------------------------------------------- /Chapter09/next/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /Chapter09/next/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "next", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "dev": "next" 8 | }, 9 | "author": "", 10 | "license": "ISC", 11 | "dependencies": { 12 | "isomorphic-fetch": "^3.0.0", 13 | "next": "^10.0.6", 14 | "react": "^17.0.1", 15 | "react-dom": "^17.0.1" 16 | }, 17 | "devDependencies": { 18 | "@types/node": "^14.14.27", 19 | "@types/react": "^17.0.2", 20 | "typescript": "^4.1.5" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Chapter09/next/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import fetch from 'isomorphic-fetch'; 2 | 3 | const App = ({ gists }) => ( 4 |
      5 | {gists.map(gist => ( 6 |
    • {gist.description}
    • 7 | ))} 8 |
    9 | ) 10 | 11 | App.getInitialProps = async () => { 12 | const response = await fetch('https://api.github.com/users/gaearon/gists') 13 | const gists = await response.json() 14 | 15 | return { 16 | gists 17 | } 18 | } 19 | 20 | export default App -------------------------------------------------------------------------------- /Chapter09/next/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "src", 4 | "esModuleInterop": true, 5 | "module": "esnext", 6 | "noImplicitAny": true, 7 | "outDir": "dist", 8 | "resolveJsonModule": true, 9 | "sourceMap": false, 10 | "target": "es6", 11 | "lib": ["dom", "dom.iterable", "esnext"], 12 | "allowJs": true, 13 | "skipLibCheck": true, 14 | "strict": true, 15 | "forceConsistentCasingInFileNames": true, 16 | "noEmit": true, 17 | "moduleResolution": "node", 18 | "isolatedModules": true, 19 | "jsx": "preserve" 20 | }, 21 | "include": ["src/**/*.ts", "src/**/*.tsx"], 22 | "exclude": ["node_modules"] 23 | } -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/.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 | -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "css-modules", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node ./dist/server", 8 | "build": "webpack" 9 | }, 10 | "author": "", 11 | "license": "ISC", 12 | "devDependencies": { 13 | "@babel/core": "^7.12.16", 14 | "@babel/preset-env": "^7.12.16", 15 | "@babel/preset-react": "^7.12.13", 16 | "css-loader": "^5.0.2", 17 | "fork-ts-checker-webpack-plugin": "^6.1.0", 18 | "html-webpack-plugin": "^5.1.0", 19 | "style-loader": "^2.0.0", 20 | "ts-loader": "^8.0.17", 21 | "typescript": "^4.1.5", 22 | "webpack": "^5.21.2", 23 | "webpack-cli": "^4.5.0", 24 | "webpack-dev-server": "^3.11.2", 25 | "webpack-node-externals": "^2.5.2" 26 | }, 27 | "dependencies": { 28 | "@types/express": "^4.17.11", 29 | "@types/react": "^17.0.2", 30 | "@types/react-dom": "^17.0.1", 31 | "express": "^4.17.1", 32 | "react": "^17.0.1", 33 | "react-dom": "^17.0.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/src/App.tsx: -------------------------------------------------------------------------------- 1 | const App = () =>
    Hello React
    2 | 3 | export default App -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/src/client.tsx: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom' 2 | import App from './App'; 3 | 4 | ReactDOM.render(, document.getElementById('app')) -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/src/declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.css' { 2 | const content: Record 3 | export default content 4 | } -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/src/server.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import express, { Request, Response } from 'express' 3 | import { renderToString } from 'react-dom/server' 4 | import path from 'path' 5 | import App from './App' 6 | import template from './template' 7 | 8 | const app = express() 9 | 10 | app.use(express.static(path.resolve(__dirname, './dist/public'))) 11 | 12 | app.get('/', (req: Request, res: Response) => { 13 | const body = renderToString() 14 | const html = template(body) 15 | res.send(html) 16 | }) 17 | 18 | app.listen(3000, () => console.log('Listening on port 3000')) -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/src/template.ts: -------------------------------------------------------------------------------- 1 | export default (body: any) => ` 2 | 3 | 4 | 5 | 6 | 7 | 8 |
    ${body}
    9 | 10 | 11 | 12 | ` -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "baseUrl": "src", 5 | "allowSyntheticDefaultImports": true, 6 | "target": "es5", 7 | "module": "commonjs", 8 | "skipLibCheck": true, 9 | "resolveJsonModule": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "isolatedModules": true, 12 | "moduleResolution": "node", 13 | "jsx": "react-jsx", 14 | "lib": ["dom", "dom.iterable", "esnext"], 15 | "strict": true, 16 | "noUnusedLocals": true, 17 | "noUnusedParameters": true, 18 | "noImplicitReturns": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "esModuleInterop": true 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.tsx"], 23 | "exclude": ["node_modules"] 24 | } -------------------------------------------------------------------------------- /Chapter09/server-side-rendering/webpack.config.js: -------------------------------------------------------------------------------- 1 | 2 | const nodeExternals = require('webpack-node-externals') 3 | const path = require('path') 4 | 5 | const mode = process.env.NODE_ENV === 'production' ? 'production' : 'development' 6 | 7 | const rules = [{ 8 | test: /\.(tsx|ts)$/, 9 | use: 'ts-loader', 10 | exclude: /node_modules/ 11 | }] 12 | 13 | const client = { 14 | mode, 15 | entry: './src/client.tsx', 16 | output: { 17 | path: path.resolve(__dirname, './dist/public'), 18 | filename: 'bundle.js', 19 | publicPath: '/' 20 | }, 21 | module: { 22 | rules 23 | }, 24 | resolve: { 25 | extensions: [".ts", ".tsx", ".js", ".json"], 26 | }, 27 | } 28 | 29 | const server = { 30 | mode, 31 | entry: './src/server.tsx', 32 | output: { 33 | path: path.resolve(__dirname, './dist'), 34 | filename: 'server.js', 35 | publicPath: '/' 36 | }, 37 | module: { 38 | rules 39 | }, 40 | target: 'node', 41 | externals: [nodeExternals()], 42 | resolve: { 43 | extensions: [".ts", ".tsx", ".js", ".json"], 44 | }, 45 | } 46 | 47 | module.exports = [client, server] -------------------------------------------------------------------------------- /Chapter10/keys/.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 | -------------------------------------------------------------------------------- /Chapter10/keys/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter10/keys/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter10/keys/public/favicon.ico -------------------------------------------------------------------------------- /Chapter10/keys/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter10/keys/public/logo192.png -------------------------------------------------------------------------------- /Chapter10/keys/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter10/keys/public/logo512.png -------------------------------------------------------------------------------- /Chapter10/keys/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 | -------------------------------------------------------------------------------- /Chapter10/keys/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter10/keys/src/App.tsx: -------------------------------------------------------------------------------- 1 | import List from './components/List' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter10/keys/src/components/List/index.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react' 2 | 3 | const List = () => { 4 | const [items, setItems] = useState(['foo', 'bar']) 5 | 6 | const handleClick = () => { 7 | const newItems = items.slice() 8 | newItems.unshift('baz') 9 | 10 | setItems(newItems) 11 | } 12 | 13 | return ( 14 |
    15 |
      16 | {items.map(item =>
    • {item}
    • )} 17 |
    18 | 19 | 20 |
    21 | ) 22 | } 23 | 24 | export default List -------------------------------------------------------------------------------- /Chapter10/keys/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter10/keys/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter10/keys/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter11/events/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /Chapter11/events/.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 | -------------------------------------------------------------------------------- /Chapter11/events/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "jsxSingleQuote": false, 5 | "printWidth": 100, 6 | "quoteProps": "as-needed", 7 | "semi": false, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "none", 11 | "useTabs": false 12 | } -------------------------------------------------------------------------------- /Chapter11/events/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | setupFilesAfterEnv: ['/setUpTests.ts'] 4 | } 5 | -------------------------------------------------------------------------------- /Chapter11/events/setUpTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom/extend-expect' 2 | -------------------------------------------------------------------------------- /Chapter11/events/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ShowInformation from './ShowInformation' 3 | 4 | const App = () => { 5 | return 6 | } 7 | 8 | export default App 9 | -------------------------------------------------------------------------------- /Chapter11/events/src/components/ShowInformation/index.test.tsx: -------------------------------------------------------------------------------- 1 | import { render, cleanup, fireEvent } from '@testing-library/react' 2 | 3 | import ShowInformation from './index' 4 | 5 | describe('Show Information Component', () => { 6 | let wrapper 7 | 8 | beforeEach(() => { 9 | wrapper = render() 10 | }) 11 | 12 | it('should modify the name', () => { 13 | const nameInput = wrapper.container.querySelector('input[name="name"]') as HTMLInputElement 14 | const ageInput = wrapper.container.querySelector('input[name="age"]') as HTMLInputElement 15 | 16 | fireEvent.change(nameInput, { target: { value: 'Carlos' } }) 17 | fireEvent.change(ageInput, { target: { value: 33 } }) 18 | 19 | expect(nameInput.value).toBe('Carlos') 20 | expect(ageInput.value).toBe('33') 21 | }) 22 | 23 | it('should show the personal information when user clicks on the button', () => { 24 | const button = wrapper.container.querySelector('button') 25 | 26 | fireEvent.click(button) 27 | 28 | const showInformation = wrapper.container.querySelector('.personalInformation') 29 | 30 | expect(showInformation).toBeInTheDocument() 31 | }) 32 | 33 | afterAll(cleanup) 34 | }) 35 | -------------------------------------------------------------------------------- /Chapter11/events/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | -------------------------------------------------------------------------------- /Chapter11/events/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from 'react-dom' 3 | import App from './components/App' 4 | 5 | render(, document.getElementById('root')) 6 | -------------------------------------------------------------------------------- /Chapter11/events/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "baseUrl": "src", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "isolatedModules": true, 9 | "jsx": "react-jsx", 10 | "lib": ["dom", "dom.iterable", "esnext"], 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noEmit": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitAny": false, 16 | "resolveJsonModule": true, 17 | "skipLibCheck": true, 18 | "sourceMap": true, 19 | "strict": true, 20 | "target": "es6" 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.tsx"], 23 | "exclude": ["node_modules"] 24 | } -------------------------------------------------------------------------------- /Chapter11/testing/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-react"] 3 | } -------------------------------------------------------------------------------- /Chapter11/testing/.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 | -------------------------------------------------------------------------------- /Chapter11/testing/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "jsxSingleQuote": false, 5 | "printWidth": 100, 6 | "quoteProps": "as-needed", 7 | "semi": false, 8 | "singleQuote": true, 9 | "tabWidth": 2, 10 | "trailingComma": "none", 11 | "useTabs": false 12 | } -------------------------------------------------------------------------------- /Chapter11/testing/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | setupFilesAfterEnv: ['/setUpTests.ts'] 4 | } 5 | -------------------------------------------------------------------------------- /Chapter11/testing/setUpTests.ts: -------------------------------------------------------------------------------- 1 | import '@testing-library/jest-dom/extend-expect' 2 | -------------------------------------------------------------------------------- /Chapter11/testing/src/components/App.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import Hello from './Hello' 3 | 4 | const App = () => { 5 | return 6 | } 7 | 8 | export default App 9 | -------------------------------------------------------------------------------- /Chapter11/testing/src/components/Hello/index.test.tsx: -------------------------------------------------------------------------------- 1 | import { render, cleanup } from '@testing-library/react' 2 | 3 | import Hello from './index' 4 | 5 | describe('Hello Component', () => { 6 | it('should render Hello World', () => { 7 | const wrapper = render() 8 | expect(wrapper.getByText('Hello World')).toBeInTheDocument() 9 | }) 10 | 11 | it('should render the name prop', () => { 12 | const wrapper = render() 13 | expect(wrapper.getByText('Hello Carlos')).toBeInTheDocument() 14 | }); 15 | 16 | it('should has .Home classname', () => { 17 | const wrapper = render() 18 | expect(wrapper.container.firstChild).toHaveClass('Hello') 19 | }); 20 | 21 | afterAll(cleanup) 22 | }) 23 | -------------------------------------------------------------------------------- /Chapter11/testing/src/components/Hello/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { FC } from 'react' 2 | 3 | type Props = { 4 | name: string 5 | } 6 | 7 | const Hello: FC = ({ name }) =>

    Hello {name || 'World'}

    8 | 9 | export default Hello -------------------------------------------------------------------------------- /Chapter11/testing/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%= htmlWebpackPlugin.options.title %> 8 | 9 | 10 |
    11 | 12 | -------------------------------------------------------------------------------- /Chapter11/testing/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import { render } from 'react-dom' 3 | import App from './components/App' 4 | 5 | render(, document.getElementById('root')) 6 | -------------------------------------------------------------------------------- /Chapter11/testing/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "baseUrl": "src", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "isolatedModules": true, 9 | "jsx": "react-jsx", 10 | "lib": ["dom", "dom.iterable", "esnext"], 11 | "module": "esnext", 12 | "moduleResolution": "node", 13 | "noEmit": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitAny": false, 16 | "resolveJsonModule": true, 17 | "skipLibCheck": true, 18 | "sourceMap": true, 19 | "strict": true, 20 | "target": "es6" 21 | }, 22 | "include": ["src/**/*.ts", "src/**/*.tsx"], 23 | "exclude": ["node_modules"] 24 | } -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/.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 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "@types/react-router-dom": "^5.1.7", 14 | "react": "^17.0.1", 15 | "react-dom": "^17.0.1", 16 | "react-router-dom": "^5.2.0", 17 | "react-scripts": "4.0.2", 18 | "typescript": "^4.1.2", 19 | "web-vitals": "^1.0.1" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter12/react-router-with-params/public/favicon.ico -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter12/react-router-with-params/public/logo192.png -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter12/react-router-with-params/public/logo512.png -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/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 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App ul.menu { 6 | margin: 50px; 7 | padding: 0; 8 | list-style: none; 9 | } 10 | 11 | .App ul.menu li { 12 | display: inline-block; 13 | padding: 0 10px; 14 | } 15 | 16 | .App ul.menu li a { 17 | color: #333; 18 | text-decoration: none; 19 | } 20 | 21 | .App ul.menu li a:hover { 22 | color: #ccc; 23 | } 24 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | import { Link } from 'react-router-dom' 3 | import './App.css' 4 | 5 | type Props = { 6 | children: ReactNode 7 | } 8 | 9 | const App: FC = ({ children }) => ( 10 |
    11 |
      12 |
    • Home
    • 13 |
    • About
    • 14 |
    • Contacts
    • 15 |
    • Contact
    • 16 |
    17 | 18 | {children} 19 |
    20 | ) 21 | 22 | export default App -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/components/About/index.tsx: -------------------------------------------------------------------------------- 1 | const About = () => ( 2 |
    3 |

    About

    4 |
    5 | ) 6 | 7 | export default About -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/components/Contact/index.tsx: -------------------------------------------------------------------------------- 1 | const Contact = () => ( 2 |
    3 |

    Contact

    4 |
    5 | ) 6 | 7 | export default Contact -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/components/Contacts/Contacts.css: -------------------------------------------------------------------------------- 1 | .Contacts ul { 2 | list-style: none; 3 | margin: 0; 4 | margin-bottom: 20px; 5 | padding: 0; 6 | } 7 | 8 | .Contacts ul li { 9 | padding: 10px; 10 | } 11 | 12 | .Contacts a { 13 | color: #555; 14 | text-decoration: none; 15 | } 16 | 17 | .Contacts a:hover { 18 | color: #ccc; 19 | text-decoration: none; 20 | } 21 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/components/Error404/index.tsx: -------------------------------------------------------------------------------- 1 | const Error404 = () => ( 2 |
    3 |

    Error404

    4 |
    5 | ) 6 | 7 | export default Error404 -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/components/Home/index.tsx: -------------------------------------------------------------------------------- 1 | const Home = () => ( 2 |
    3 |

    Home

    4 |
    5 | ) 6 | 7 | export default Home -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { render } from 'react-dom' 3 | import { BrowserRouter as Router } from 'react-router-dom' 4 | 5 | // Routes 6 | import AppRoutes from './routes' 7 | 8 | render( 9 | 10 | 11 | , 12 | document.getElementById('root') 13 | ) -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/src/routes.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { Route, Switch } from 'react-router-dom' 3 | 4 | // Components 5 | import App from './App' 6 | import About from './components/About' 7 | import Contact from './components/Contact' 8 | import Home from './components/Home' 9 | import Error404 from './components/Error404' 10 | import Contacts from './components/Contacts' 11 | 12 | const AppRoutes = () => ( 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ) 24 | 25 | export default AppRoutes -------------------------------------------------------------------------------- /Chapter12/react-router-with-params/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter12/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 | -------------------------------------------------------------------------------- /Chapter12/react-router/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "@types/react-router-dom": "^5.1.7", 14 | "react": "^17.0.1", 15 | "react-dom": "^17.0.1", 16 | "react-router-dom": "^5.2.0", 17 | "react-scripts": "4.0.2", 18 | "typescript": "^4.1.2", 19 | "web-vitals": "^1.0.1" 20 | }, 21 | "scripts": { 22 | "start": "react-scripts start", 23 | "build": "react-scripts build", 24 | "test": "react-scripts test", 25 | "eject": "react-scripts eject" 26 | }, 27 | "eslintConfig": { 28 | "extends": [ 29 | "react-app", 30 | "react-app/jest" 31 | ] 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.2%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Chapter12/react-router/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter12/react-router/public/favicon.ico -------------------------------------------------------------------------------- /Chapter12/react-router/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter12/react-router/public/logo192.png -------------------------------------------------------------------------------- /Chapter12/react-router/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter12/react-router/public/logo512.png -------------------------------------------------------------------------------- /Chapter12/react-router/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 | -------------------------------------------------------------------------------- /Chapter12/react-router/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter12/react-router/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | animation: App-logo-spin infinite 20s linear; 7 | height: 40vmin; 8 | pointer-events: none; 9 | } 10 | 11 | .App-header { 12 | background-color: #282c34; 13 | min-height: 100vh; 14 | display: flex; 15 | flex-direction: column; 16 | align-items: center; 17 | justify-content: center; 18 | font-size: calc(10px + 2vmin); 19 | color: white; 20 | } 21 | 22 | .App-link { 23 | color: #61dafb; 24 | } 25 | 26 | @keyframes App-logo-spin { 27 | from { 28 | transform: rotate(0deg); 29 | } 30 | to { 31 | transform: rotate(360deg); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Chapter12/react-router/src/App.tsx: -------------------------------------------------------------------------------- 1 | import { FC, ReactNode } from 'react' 2 | import './App.css' 3 | 4 | type Props = { 5 | children: ReactNode 6 | } 7 | 8 | const App: FC = ({ children }) => ( 9 |
    10 | {children} 11 |
    12 | ) 13 | 14 | export default App -------------------------------------------------------------------------------- /Chapter12/react-router/src/components/About.tsx: -------------------------------------------------------------------------------- 1 | const About = () => ( 2 |
    3 |

    About

    4 |
    5 | ) 6 | 7 | export default About -------------------------------------------------------------------------------- /Chapter12/react-router/src/components/Contact.tsx: -------------------------------------------------------------------------------- 1 | const Contact = () => ( 2 |
    3 |

    Contact

    4 |
    5 | ) 6 | 7 | export default Contact -------------------------------------------------------------------------------- /Chapter12/react-router/src/components/Error404.tsx: -------------------------------------------------------------------------------- 1 | const Error404 = () => ( 2 |
    3 |

    Error404

    4 |
    5 | ) 6 | 7 | export default Error404 -------------------------------------------------------------------------------- /Chapter12/react-router/src/components/Home.tsx: -------------------------------------------------------------------------------- 1 | const Home = () => ( 2 |
    3 |

    Home

    4 |
    5 | ) 6 | 7 | export default Home -------------------------------------------------------------------------------- /Chapter12/react-router/src/index.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { render } from 'react-dom' 3 | import { BrowserRouter as Router } from 'react-router-dom' 4 | 5 | // Routes 6 | import AppRoutes from './routes' 7 | 8 | render( 9 | 10 | 11 | , 12 | document.getElementById('root') 13 | ) -------------------------------------------------------------------------------- /Chapter12/react-router/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter12/react-router/src/routes.tsx: -------------------------------------------------------------------------------- 1 | // Dependencies 2 | import { Route, Switch } from 'react-router-dom' 3 | 4 | // Components 5 | import App from './App' 6 | import About from './components/About' 7 | import Contact from './components/Contact' 8 | import Home from './components/Home' 9 | import Error404 from './components/Error404' 10 | 11 | const AppRoutes = () => ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | ) 21 | 22 | export default AppRoutes -------------------------------------------------------------------------------- /Chapter12/react-router/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter13/counter/.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 | -------------------------------------------------------------------------------- /Chapter13/counter/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter13/counter/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter13/counter/public/favicon.ico -------------------------------------------------------------------------------- /Chapter13/counter/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter13/counter/public/logo192.png -------------------------------------------------------------------------------- /Chapter13/counter/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter13/counter/public/logo512.png -------------------------------------------------------------------------------- /Chapter13/counter/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 | -------------------------------------------------------------------------------- /Chapter13/counter/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter13/counter/src/App.tsx: -------------------------------------------------------------------------------- 1 | import Counter from './components/Counter' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter13/counter/src/components/Counter/index.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useState } from 'react' 2 | 3 | type Props = { 4 | initialCount: number 5 | } 6 | 7 | const Counter: FC = (props) => { 8 | const [state, setState] = useState({ count: props.initialCount }) 9 | 10 | const handleClick = () => { 11 | setState({ 12 | count: state.count + 1 13 | }) 14 | } 15 | 16 | return ( 17 |
    18 | {state.count} 19 | 20 |
    21 | ) 22 | } 23 | 24 | export default Counter -------------------------------------------------------------------------------- /Chapter13/counter/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter13/counter/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter13/counter/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /Chapter13/keys/.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 | -------------------------------------------------------------------------------- /Chapter13/keys/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hocs", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "@types/jest": "^26.0.15", 10 | "@types/node": "^12.0.0", 11 | "@types/react": "^17.0.0", 12 | "@types/react-dom": "^17.0.0", 13 | "react": "^17.0.1", 14 | "react-dom": "^17.0.1", 15 | "react-scripts": "4.0.2", 16 | "typescript": "^4.1.2", 17 | "web-vitals": "^1.0.1" 18 | }, 19 | "scripts": { 20 | "start": "react-scripts start", 21 | "build": "react-scripts build", 22 | "test": "react-scripts test", 23 | "eject": "react-scripts eject" 24 | }, 25 | "eslintConfig": { 26 | "extends": [ 27 | "react-app", 28 | "react-app/jest" 29 | ] 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Chapter13/keys/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter13/keys/public/favicon.ico -------------------------------------------------------------------------------- /Chapter13/keys/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter13/keys/public/logo192.png -------------------------------------------------------------------------------- /Chapter13/keys/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/React-17-Design-Patterns-and-Best-Practices-Third-Edition/4bee2e46f465ba245400e1c4a9164730ccb83640/Chapter13/keys/public/logo512.png -------------------------------------------------------------------------------- /Chapter13/keys/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 | -------------------------------------------------------------------------------- /Chapter13/keys/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Chapter13/keys/src/App.tsx: -------------------------------------------------------------------------------- 1 | import List from './components/List' 2 | 3 | function App() { 4 | return ( 5 |
    6 | 7 |
    8 | ) 9 | } 10 | 11 | export default App -------------------------------------------------------------------------------- /Chapter13/keys/src/components/List/index.tsx: -------------------------------------------------------------------------------- 1 | import { FC, useState } from 'react' 2 | 3 | const List: FC = () => { 4 | const [items, setItems] = useState(['foo', 'bar']) 5 | 6 | const handleClick = () => { 7 | const newItems = items.slice() 8 | newItems.unshift('baz') 9 | 10 | setItems(newItems) 11 | } 12 | 13 | // return ( 14 | //
    15 | //
      16 | // {items.map((item, index) => ( 17 | //
    • {item}
    • 18 | // ))} 19 | //
    20 | 21 | // 22 | //
    23 | // ) 24 | 25 | return ( 26 |
    27 |
      28 | {items.map((item, index) => ( 29 |
    • 30 | {item} 31 | 32 |
    • 33 | ))} 34 |
    35 | 36 |
    37 | ) 38 | } 39 | 40 | export default List -------------------------------------------------------------------------------- /Chapter13/keys/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | ReactDOM.render( 6 | 7 | 8 | , 9 | document.getElementById('root') 10 | ); 11 | -------------------------------------------------------------------------------- /Chapter13/keys/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /Chapter13/keys/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "module": "esnext", 17 | "moduleResolution": "node", 18 | "resolveJsonModule": true, 19 | "isolatedModules": true, 20 | "noEmit": true, 21 | "jsx": "react-jsx" 22 | }, 23 | "include": [ 24 | "src" 25 | ] 26 | } 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Packt 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | --------------------------------------------------------------------------------