1- import React , { useState , useCallback } from 'react' ;
1+ import React , { useState , useCallback , useRef } from 'react' ;
22import classnames from 'classnames' ;
3+ import { useFormState } from 'react-use-form-state' ;
34
45import './index.css' ;
56
6- const encode = data => {
7+ const encode = ( data ) => {
78 return Object . keys ( data )
8- . map ( key => encodeURIComponent ( key ) + '=' + encodeURIComponent ( data [ key ] ) )
9+ . map ( ( key ) => encodeURIComponent ( key ) + '=' + encodeURIComponent ( data [ key ] ) )
910 . join ( '&' ) ;
1011} ;
1112
12- export default props => {
13- const [ name , setName ] = useState ( '' ) ;
14- const [ email , setEmail ] = useState ( '' ) ;
15- const [ message , setMessage ] = useState ( '' ) ;
16- const [ city , setCity ] = useState ( '' ) ;
13+ export default ( props ) => {
14+ const [ formState , { text, email, textarea } ] = useFormState ( ) ;
1715 const [ feedbackMessage , setFeedbackMessage ] = useState ( '' ) ;
18-
19- const onChangeName = useCallback ( e => setName ( e . target . value ) , [ ] ) ;
20- const onChangeEmail = useCallback ( e => setEmail ( e . target . value ) , [ ] ) ;
21- const onChangeMessage = useCallback ( e => setMessage ( e . target . value ) , [ ] ) ;
22- const onChangeCity = useCallback ( e => setCity ( e . target . value ) , [ ] ) ;
16+ const [ sendingMessage , setSendingMessage ] = useState ( false ) ;
17+ const formRef = useRef ( ) ;
2318
2419 const onSubmit = useCallback (
25- async e => {
20+ async ( e ) => {
2621 e . preventDefault ( ) ;
2722
23+ if ( ! isFormValid ( formState ) ) {
24+ setFeedbackMessage ( 'Please complete all required fields' ) ;
25+ return ;
26+ }
27+
28+ if ( sendingMessage ) {
29+ return ;
30+ }
31+
32+ setFeedbackMessage ( 'Sending your message now 🚀' ) ;
33+ setSendingMessage ( true ) ;
34+
2835 try {
2936 const response = await fetch ( '/' , {
3037 method : 'POST' ,
3138 headers : { 'Content-Type' : 'application/x-www-form-urlencoded' } ,
3239 body : encode ( {
3340 'form-name' : 'contact' ,
34- name,
35- email,
36- city,
37- message,
41+ name : formState . values . name ,
42+ email : formState . values . email ,
43+ city : formState . values . city ,
44+ message : formState . values . message ,
3845 } ) ,
3946 } ) ;
4047
41- console . log ( 'response' , response ) ;
48+ if ( response . status !== 200 ) {
49+ throw new Error ( 'unable to send message' ) ;
50+ }
4251
4352 setFeedbackMessage ( 'Thank you!' ) ;
53+ formState . clear ( ) ;
54+ formRef . current . reset ( ) ;
4455 } catch ( e ) {
4556 console . error ( 'error' , e ) ;
4657 setFeedbackMessage ( 'Unable to send the message, please try again' ) ;
58+ } finally {
59+ setSendingMessage ( false ) ;
4760 }
4861 } ,
49- [ name , email , city , message ]
62+ [ formState . values , sendingMessage ]
5063 ) ;
5164
5265 return (
@@ -55,69 +68,46 @@ export default props => {
5568 onSubmit = { onSubmit }
5669 className = "Form"
5770 name = "contact"
71+ ref = { formRef }
5872 >
5973 < input type = "hidden" name = "form-name" value = "contact" />
6074
61- < Input
62- component = "input"
63- type = "name"
64- name = "name"
65- value = { name }
66- onChange = { onChangeName }
67- required
68- label = "Name*"
69- />
70-
71- < Input
72- component = "input"
73- type = "email"
74- name = "email"
75- value = { email }
76- onChange = { onChangeEmail }
77- required
78- label = "Email*"
79- />
80-
81- < Input
82- component = "input"
83- type = "text"
84- name = "city"
85- value = { city }
86- onChange = { onChangeCity }
87- label = "City"
88- />
89-
90- < Input
91- required
92- name = "message"
93- component = "textarea"
94- value = { message }
95- onChange = { onChangeMessage }
96- label = "Message*"
97- />
75+ < Input { ...text ( 'name' ) } required label = "Name*" />
76+
77+ < Input { ...email ( 'email' ) } required label = "Email*" />
78+
79+ < Input { ...text ( 'city' ) } label = "City" />
80+
81+ < Input { ...textarea ( 'message' ) } type = "textarea" label = "Message*" />
82+
83+ { feedbackMessage && (
84+ < p className = "Form--feedback-message" > { feedbackMessage } </ p >
85+ ) }
9886
9987 < div className = "Form--submit-container" >
100- < button type = "submit" > Send</ button >
88+ < button disabled = { sendingMessage } type = "submit" >
89+ Send
90+ </ button >
10191 </ div >
102-
103- { feedbackMessage && < p > { feedbackMessage } </ p > }
10492 </ form >
10593 ) ;
10694} ;
10795
108- const Input = props => {
109- const { component , label, className, ...others } = props ;
96+ const Input = ( props ) => {
97+ const { type , label, className, ...others } = props ;
11098 let input ;
11199
112- switch ( component ) {
100+ switch ( type ) {
101+ case 'text' :
102+ case 'email' :
113103 case 'input' :
114- input = < input { ...others } /> ;
104+ input = < input type = { type } { ...others } /> ;
115105 break ;
116106 case 'textarea' :
117- input = < textarea { ...others } /> ;
107+ input = < textarea type = { type } { ...others } /> ;
118108 break ;
119109 default :
120- throw new Error ( ' Ops' ) ;
110+ throw new Error ( ` Ops: ${ type } ` ) ;
121111 }
122112
123113 const classes = classnames ( className , {
@@ -131,3 +121,8 @@ const Input = props => {
131121 </ label >
132122 ) ;
133123} ;
124+
125+ const isFormValid = ( formState ) =>
126+ formState . validity . name &&
127+ formState . validity . email &&
128+ formState . validity . message ;
0 commit comments