@@ -8,6 +8,7 @@ import React, {
88 Dispatch ,
99 SetStateAction ,
1010 ReactNode ,
11+ useCallback ,
1112} from 'react' ;
1213
1314import GoTrue , {
@@ -36,6 +37,12 @@ const defaultSettings = {
3637 } ,
3738} ;
3839
40+ const errors = {
41+ noUserFound : 'No current user found - are you logged in?' ,
42+ } ;
43+
44+ type MaybeUserPromise = Promise < User | undefined > ;
45+
3946export type ReactNetlifyIdentityAPI = {
4047 user : User | undefined ;
4148 /** 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 = {
4653 email : string ,
4754 password : string ,
4855 data : Object
49- ) => Promise < User | undefined > ;
56+ ) => MaybeUserPromise ;
5057 loginUser : (
5158 email : string ,
5259 password : string ,
5360 remember ?: boolean
54- ) => Promise < User | undefined > ;
55- logoutUser : ( ) => Promise < User | undefined > ;
61+ ) => MaybeUserPromise ;
62+ logoutUser : ( ) => MaybeUserPromise ;
5663 requestPasswordRecovery : ( email : string ) => Promise < void > ;
5764 recoverAccount : (
5865 token : string ,
5966 remember ?: boolean | undefined
6067 ) => Promise < User > ;
61- updateUser : ( fields : { data : object } ) => Promise < User | undefined > ;
68+ updateUser : ( fields : { data : object } ) => MaybeUserPromise ;
6269 getFreshJWT : ( ) => Promise < string > ;
6370 authedFetch : {
6471 get : ( endpoint : string , obj ?: { } ) => Promise < any > ;
@@ -119,14 +126,20 @@ export function useNetlifyIdentity(
119126 [ url ]
120127 ) ;
121128
129+ /******* STATE and EFFECTS */
130+
122131 const [ user , setUser ] = useState < User | undefined > (
123132 goTrueInstance . currentUser ( ) || undefined
124133 ) ;
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+ ) ;
130143
131144 const [ param , setParam ] = useState < TokenParam > ( defaultParam ) ;
132145
@@ -140,71 +153,109 @@ export function useNetlifyIdentity(
140153 }
141154 } , [ ] ) ;
142155
156+ const [ settings , setSettings ] = useState < Settings > ( defaultSettings ) ;
157+
158+ useEffect ( ( ) => {
159+ goTrueInstance . settings
160+ . bind ( goTrueInstance ) ( )
161+ . then ( x => setSettings ( x ) ) ;
162+ } , [ ] ) ;
163+
143164 /******* OPERATIONS */
144165 // make sure the Registration preferences under Identity settings in your Netlify dashboard are set to Open.
145166 // 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
146167 /******* external oauth */
147168
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+ ) ;
159182
160183 /******* 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+
176214 return user !
177215 . update ( fields ) // e.g. { data: { email: "example@example.com", password: "password" } }
178216 . then ( _setUser ) ;
217+ } ,
218+ [ user ]
219+ ) ;
220+
221+ const getFreshJWT = useCallback ( ( ) => {
222+ if ( ! user ) {
223+ throw new Error ( errors . noUserFound ) ;
179224 }
180- } ;
181- const getFreshJWT = ( ) => {
182- if ( ! user ) throw new Error ( 'No current user found - are you logged in?' ) ;
225+
183226 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+
187234 return user . logout ( ) . then ( ( ) => _setUser ( undefined ) ) ;
188- } ;
235+ } , [ user ] ) ;
189236
190237 const genericAuthedFetch = ( method : string ) => (
191238 endpoint : string ,
192- obj = { }
239+ options : RequestInit = { }
193240 ) => {
194- if ( ! user || ! user . token || ! user . token . access_token )
241+ if ( ! user ? .token ?. access_token ) {
195242 throw new Error ( 'no user token found' ) ;
243+ }
244+
196245 const defaultObj = {
197246 headers : {
198247 Accept : 'application/json' ,
199248 'Content-Type' : 'application/json' ,
200249 Authorization : 'Bearer ' + user . token . access_token ,
201250 } ,
202251 } ;
203- const finalObj = Object . assign ( defaultObj , { method } , obj ) ;
252+ const finalObj = Object . assign ( defaultObj , { method } , options ) ;
253+
204254 return fetch ( endpoint , finalObj ) . then ( res =>
205255 finalObj . headers [ 'Content-Type' ] === 'application/json' ? res . json ( ) : res
206256 ) ;
207257 } ;
258+
208259 const authedFetch = {
209260 get : genericAuthedFetch ( 'GET' ) ,
210261 post : genericAuthedFetch ( 'POST' ) ,
0 commit comments