@@ -8,6 +8,7 @@ import React, {
8
8
Dispatch ,
9
9
SetStateAction ,
10
10
ReactNode ,
11
+ useCallback ,
11
12
} from 'react' ;
12
13
13
14
import GoTrue , {
@@ -36,6 +37,12 @@ const defaultSettings = {
36
37
} ,
37
38
} ;
38
39
40
+ const errors = {
41
+ noUserFound : 'No current user found - are you logged in?' ,
42
+ } ;
43
+
44
+ type MaybeUserPromise = Promise < User | undefined > ;
45
+
39
46
export type ReactNetlifyIdentityAPI = {
40
47
user : User | undefined ;
41
48
/** not meant for normal use! you should mostly use one of the other exported methods to update the user instance */
@@ -46,19 +53,19 @@ export type ReactNetlifyIdentityAPI = {
46
53
email : string ,
47
54
password : string ,
48
55
data : Object
49
- ) => Promise < User | undefined > ;
56
+ ) => MaybeUserPromise ;
50
57
loginUser : (
51
58
email : string ,
52
59
password : string ,
53
60
remember ?: boolean
54
- ) => Promise < User | undefined > ;
55
- logoutUser : ( ) => Promise < User | undefined > ;
61
+ ) => MaybeUserPromise ;
62
+ logoutUser : ( ) => MaybeUserPromise ;
56
63
requestPasswordRecovery : ( email : string ) => Promise < void > ;
57
64
recoverAccount : (
58
65
token : string ,
59
66
remember ?: boolean | undefined
60
67
) => Promise < User > ;
61
- updateUser : ( fields : { data : object } ) => Promise < User | undefined > ;
68
+ updateUser : ( fields : { data : object } ) => MaybeUserPromise ;
62
69
getFreshJWT : ( ) => Promise < string > ;
63
70
authedFetch : {
64
71
get : ( endpoint : string , obj ?: { } ) => Promise < any > ;
@@ -119,14 +126,20 @@ export function useNetlifyIdentity(
119
126
[ url ]
120
127
) ;
121
128
129
+ /******* STATE and EFFECTS */
130
+
122
131
const [ user , setUser ] = useState < User | undefined > (
123
132
goTrueInstance . currentUser ( ) || undefined
124
133
) ;
125
- const _setUser = ( _user : User | undefined ) => {
126
- setUser ( _user ) ;
127
- onAuthChange ( _user ) ; // if someone's subscribed to auth changes, let 'em know
128
- return _user ; // so that we can continue chaining
129
- } ;
134
+
135
+ const _setUser = useCallback (
136
+ ( _user : User | undefined ) => {
137
+ setUser ( _user ) ;
138
+ onAuthChange ( _user ) ; // if someone's subscribed to auth changes, let 'em know
139
+ return _user ; // so that we can continue chaining
140
+ } ,
141
+ [ onAuthChange ]
142
+ ) ;
130
143
131
144
const [ param , setParam ] = useState < TokenParam > ( defaultParam ) ;
132
145
@@ -140,71 +153,109 @@ export function useNetlifyIdentity(
140
153
}
141
154
} , [ ] ) ;
142
155
156
+ const [ settings , setSettings ] = useState < Settings > ( defaultSettings ) ;
157
+
158
+ useEffect ( ( ) => {
159
+ goTrueInstance . settings
160
+ . bind ( goTrueInstance ) ( )
161
+ . then ( x => setSettings ( x ) ) ;
162
+ } , [ ] ) ;
163
+
143
164
/******* OPERATIONS */
144
165
// make sure the Registration preferences under Identity settings in your Netlify dashboard are set to Open.
145
166
// https://react-netlify-identity.netlify.com/login#access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NTY0ODY3MjEsInN1YiI6ImNiZjY5MTZlLTNlZGYtNGFkNS1iOTYzLTQ4ZTY2NDcyMDkxNyIsImVtYWlsIjoic2hhd250aGUxQGdtYWlsLmNvbSIsImFwcF9tZXRhZGF0YSI6eyJwcm92aWRlciI6ImdpdGh1YiJ9LCJ1c2VyX21ldGFkYXRhIjp7ImF2YXRhcl91cmwiOiJodHRwczovL2F2YXRhcnMxLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzY3NjQ5NTc_dj00IiwiZnVsbF9uYW1lIjoic3d5eCJ9fQ.E8RrnuCcqq-mLi1_Q5WHJ-9THIdQ3ha1mePBKGhudM0&expires_in=3600&refresh_token=OyA_EdRc7WOIVhY7RiRw5w&token_type=bearer
146
167
/******* external oauth */
147
168
148
- const loginProvider = ( provider : Provider ) => {
149
- const url = goTrueInstance . loginExternalUrl ( provider ) ;
150
- window . location . href = url ;
151
- } ;
152
- const acceptInviteExternalUrl = ( provider : Provider , token : string ) =>
153
- goTrueInstance . acceptInviteExternalUrl ( provider , token ) ;
154
- const _settings = goTrueInstance . settings . bind ( goTrueInstance ) ;
155
- const [ settings , setSettings ] = useState < Settings > ( defaultSettings ) ;
156
- useEffect ( ( ) => {
157
- _settings ( ) . then ( x => setSettings ( x ) ) ;
158
- } , [ ] ) ;
169
+ const loginProvider = useCallback (
170
+ ( provider : Provider ) => {
171
+ const url = goTrueInstance . loginExternalUrl ( provider ) ;
172
+ window . location . href = url ;
173
+ } ,
174
+ [ goTrueInstance ]
175
+ ) ;
176
+
177
+ const acceptInviteExternalUrl = useCallback (
178
+ ( provider : Provider , token : string ) =>
179
+ goTrueInstance . acceptInviteExternalUrl ( provider , token ) ,
180
+ [ goTrueInstance ]
181
+ ) ;
159
182
160
183
/******* email auth */
161
- const signupUser = ( email : string , password : string , data : Object ) =>
162
- goTrueInstance . signup ( email , password , data ) . then ( _setUser ) ; // TODO: make setUser optional?
163
- const loginUser = (
164
- email : string ,
165
- password : string ,
166
- remember : boolean = true
167
- ) => goTrueInstance . login ( email , password , remember ) . then ( _setUser ) ;
168
- const requestPasswordRecovery = ( email : string ) =>
169
- goTrueInstance . requestPasswordRecovery ( email ) ;
170
- const recoverAccount = ( token : string , remember ?: boolean | undefined ) =>
171
- goTrueInstance . recover ( token , remember ) ;
172
- const updateUser = ( fields : { data : object } ) => {
173
- if ( user == null ) {
174
- throw new Error ( 'No current user found - are you logged in?' ) ;
175
- } else {
184
+ const signupUser = useCallback (
185
+ ( email : string , password : string , data : Object ) =>
186
+ // TODO: make setUser optional?
187
+ goTrueInstance . signup ( email , password , data ) . then ( _setUser ) ,
188
+ [ goTrueInstance ]
189
+ ) ;
190
+
191
+ const loginUser = useCallback (
192
+ ( email : string , password : string , remember : boolean = true ) =>
193
+ goTrueInstance . login ( email , password , remember ) . then ( _setUser ) ,
194
+ [ goTrueInstance , _setUser ]
195
+ ) ;
196
+
197
+ const requestPasswordRecovery = useCallback (
198
+ ( email : string ) => goTrueInstance . requestPasswordRecovery ( email ) ,
199
+ [ goTrueInstance ]
200
+ ) ;
201
+
202
+ const recoverAccount = useCallback (
203
+ ( token : string , remember ?: boolean | undefined ) =>
204
+ goTrueInstance . recover ( token , remember ) ,
205
+ [ goTrueInstance ]
206
+ ) ;
207
+
208
+ const updateUser = useCallback (
209
+ ( fields : { data : object } ) => {
210
+ if ( ! user ) {
211
+ throw new Error ( errors . noUserFound ) ;
212
+ }
213
+
176
214
return user !
177
215
. update ( fields ) // e.g. { data: { email: "example@example.com", password: "password" } }
178
216
. then ( _setUser ) ;
217
+ } ,
218
+ [ user ]
219
+ ) ;
220
+
221
+ const getFreshJWT = useCallback ( ( ) => {
222
+ if ( ! user ) {
223
+ throw new Error ( errors . noUserFound ) ;
179
224
}
180
- } ;
181
- const getFreshJWT = ( ) => {
182
- if ( ! user ) throw new Error ( 'No current user found - are you logged in?' ) ;
225
+
183
226
return user . jwt ( ) ;
184
- } ;
185
- const logoutUser = ( ) => {
186
- if ( ! user ) throw new Error ( 'No current user found - are you logged in?' ) ;
227
+ } , [ user ] ) ;
228
+
229
+ const logoutUser = useCallback ( ( ) => {
230
+ if ( ! user ) {
231
+ throw new Error ( errors . noUserFound ) ;
232
+ }
233
+
187
234
return user . logout ( ) . then ( ( ) => _setUser ( undefined ) ) ;
188
- } ;
235
+ } , [ user ] ) ;
189
236
190
237
const genericAuthedFetch = ( method : string ) => (
191
238
endpoint : string ,
192
- obj = { }
239
+ options : RequestInit = { }
193
240
) => {
194
- if ( ! user || ! user . token || ! user . token . access_token )
241
+ if ( ! user ? .token ?. access_token ) {
195
242
throw new Error ( 'no user token found' ) ;
243
+ }
244
+
196
245
const defaultObj = {
197
246
headers : {
198
247
Accept : 'application/json' ,
199
248
'Content-Type' : 'application/json' ,
200
249
Authorization : 'Bearer ' + user . token . access_token ,
201
250
} ,
202
251
} ;
203
- const finalObj = Object . assign ( defaultObj , { method } , obj ) ;
252
+ const finalObj = Object . assign ( defaultObj , { method } , options ) ;
253
+
204
254
return fetch ( endpoint , finalObj ) . then ( res =>
205
255
finalObj . headers [ 'Content-Type' ] === 'application/json' ? res . json ( ) : res
206
256
) ;
207
257
} ;
258
+
208
259
const authedFetch = {
209
260
get : genericAuthedFetch ( 'GET' ) ,
210
261
post : genericAuthedFetch ( 'POST' ) ,
0 commit comments