├── .gitignore ├── README.md ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.css ├── App.tsx ├── index.css ├── index.tsx ├── logo.svg ├── react-app-env.d.ts ├── reportWebVitals.ts └── setupTests.ts ├── tsconfig.json └── yarn.lock /.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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # React Hook Form Typescript with Validation example using react-hook-form 7 and Bootstrap 4 2 | 3 | For instruction, please visit: 4 | > [React Hook Form Typescript with Validation example](https://bezkoder.com/react-hook-form-typescript/) 5 | 6 | More Practice: 7 | > [(Javascript) React Hook Form Validation example](https://bezkoder.com/react-form-validation-hooks/) 8 | 9 | > [React Hooks (without Redux) CRUD example with Axios and Web API](https://bezkoder.com/react-hooks-crud-axios-api/) 10 | 11 | > [React Hooks + Redux CRUD example with Axios & Web API](https://bezkoder.com/react-hooks-redux-crud/) 12 | 13 | > [React Table example: CRUD App with react-table v7](https://bezkoder.com/react-table-example-hooks-crud/) 14 | 15 | > [React Pagination using Hooks example](https://bezkoder.com/react-pagination-hooks/) 16 | 17 | > [React Hooks File Upload example](https://bezkoder.com/react-hooks-file-upload/) 18 | 19 | > [React Hooks: JWT Authentication & Authorization example](https://bezkoder.com/react-hooks-jwt-auth/) 20 | 21 | > [React + Redux + Hooks: JWT Authentication & Authorization example](https://bezkoder.com/react-hooks-redux-login-registration-example/) 22 | 23 | Fullstack with Node.js Express: 24 | > [React + Node.js Express + MySQL](https://bezkoder.com/react-node-express-mysql/) 25 | 26 | > [React + Node.js Express + PostgreSQL](https://bezkoder.com/react-node-express-postgresql/) 27 | 28 | > [React + Node.js Express + MongoDB](https://bezkoder.com/react-node-express-mongodb-mern-stack/) 29 | 30 | Fullstack with Spring Boot: 31 | > [React + Spring Boot + MySQL](https://bezkoder.com/react-spring-boot-crud/) 32 | 33 | > [React + Spring Boot + PostgreSQL](https://bezkoder.com/spring-boot-react-postgresql/) 34 | 35 | > [React + Spring Boot + MongoDB](https://bezkoder.com/react-spring-boot-mongodb/) 36 | 37 | Fullstack with Django: 38 | > [React.js Hooks + Django Rest Framework](https://bezkoder.com/django-react-hooks/) 39 | 40 | Serverless with Firebase: 41 | > [React Firebase Hooks: CRUD App with Realtime Database example](https://bezkoder.com/react-firebase-hooks-crud/) 42 | 43 | > [React Hooks Firestore example: CRUD App](https://bezkoder.com/react-hooks-firestore/) 44 | 45 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). 46 | 47 | ## Project setup 48 | 49 | In the project directory, you can run: 50 | 51 | ``` 52 | npm install 53 | # or 54 | yarn install 55 | ``` 56 | 57 | or 58 | 59 | ### Compiles and hot-reloads for development 60 | 61 | ``` 62 | npm start 63 | # or 64 | yarn start 65 | ``` 66 | 67 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser. 68 | 69 | The page will reload if you make edits. 70 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-hook-form-typescript", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@hookform/resolvers": "^2.6.0", 7 | "@testing-library/jest-dom": "^5.11.4", 8 | "@testing-library/react": "^11.1.0", 9 | "@testing-library/user-event": "^12.1.10", 10 | "@types/jest": "^26.0.15", 11 | "@types/node": "^12.0.0", 12 | "@types/react": "^17.0.0", 13 | "@types/react-dom": "^17.0.0", 14 | "react": "^17.0.2", 15 | "react-dom": "^17.0.2", 16 | "react-hook-form": "^7.10.1", 17 | "react-scripts": "4.0.3", 18 | "typescript": "^4.1.2", 19 | "web-vitals": "^1.0.1", 20 | "yup": "^0.32.9" 21 | }, 22 | "scripts": { 23 | "start": "react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": [ 30 | "react-app", 31 | "react-app/jest" 32 | ] 33 | }, 34 | "browserslist": { 35 | "production": [ 36 | ">0.2%", 37 | "not dead", 38 | "not op_mini all" 39 | ], 40 | "development": [ 41 | "last 1 chrome version", 42 | "last 1 firefox version", 43 | "last 1 safari version" 44 | ] 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-hook-form-typescript/f0c0186dfe16a7606ea2c942ae8e62abdad191e7/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | 28 | React App 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-hook-form-typescript/f0c0186dfe16a7606ea2c942ae8e62abdad191e7/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bezkoder/react-hook-form-typescript/f0c0186dfe16a7606ea2c942ae8e62abdad191e7/public/logo512.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | p { 2 | font-family: Lato; 3 | } 4 | 5 | #root { 6 | padding: 30px; 7 | } 8 | 9 | .register-form { 10 | max-width: 350px; 11 | margin: auto; 12 | } 13 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import './App.css'; 2 | import React from 'react'; 3 | import { useForm } from 'react-hook-form'; 4 | import { yupResolver } from '@hookform/resolvers/yup'; 5 | import * as Yup from 'yup'; 6 | 7 | type UserSubmitForm = { 8 | fullname: string; 9 | username: string; 10 | email: string; 11 | password: string; 12 | confirmPassword: string; 13 | acceptTerms: boolean; 14 | }; 15 | 16 | const App: React.FC = () => { 17 | const validationSchema = Yup.object().shape({ 18 | fullname: Yup.string().required('Fullname is required'), 19 | username: Yup.string() 20 | .required('Username is required') 21 | .min(6, 'Username must be at least 6 characters') 22 | .max(20, 'Username must not exceed 20 characters'), 23 | email: Yup.string() 24 | .required('Email is required') 25 | .email('Email is invalid'), 26 | password: Yup.string() 27 | .required('Password is required') 28 | .min(6, 'Password must be at least 6 characters') 29 | .max(40, 'Password must not exceed 40 characters'), 30 | confirmPassword: Yup.string() 31 | .required('Confirm Password is required') 32 | .oneOf([Yup.ref('password'), null], 'Confirm Password does not match'), 33 | acceptTerms: Yup.bool().oneOf([true], 'Accept Terms is required') 34 | }); 35 | 36 | const { 37 | register, 38 | handleSubmit, 39 | reset, 40 | formState: { errors } 41 | } = useForm({ 42 | resolver: yupResolver(validationSchema) 43 | }); 44 | 45 | const onSubmit = (data: UserSubmitForm) => { 46 | console.log(JSON.stringify(data, null, 2)); 47 | }; 48 | 49 | return ( 50 |
51 |
52 |
53 | 54 | 59 |
{errors.fullname?.message}
60 |
61 | 62 |
63 | 64 | 69 |
{errors.username?.message}
70 |
71 | 72 |
73 | 74 | 79 |
{errors.email?.message}
80 |
81 | 82 |
83 | 84 | 89 |
{errors.password?.message}
90 |
91 |
92 | 93 | 100 |
101 | {errors.confirmPassword?.message} 102 |
103 |
104 | 105 |
106 | 113 | 116 |
{errors.acceptTerms?.message}
117 |
118 | 119 |
120 | 123 | 130 |
131 |
132 |
133 | ); 134 | }; 135 | 136 | export default App; 137 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------