ReactJS
Users
SignIn with Google
9 min
react google login introduction in the last tutorial, you built a user login/logout feature to your app using the parse user parse user class now you will learn how to use google sign in to retrieve user data from google and log in, sign up or link existent users with it you will also install and configure react google login react google login lib to achieve that the parse user linkwith parse user linkwith method is responsible for signing up and logging in users using any third party authentication method, as long as you pass the right parameters requested by each different provider after linking the user data to a new or existent parse user parse user , parse will store a valid user session on your device future calls to methods like current current will successfully retrieve your user data, just like with regular logins prerequisites to complete this tutorial, you will need a react app created and connected to back4app complete the previous guide so you can have a better understanding of the parse user class and the parse user login method https //www back4app com/docs/react/working with users/react user login if you want to test/use the screen layout provided by this guide, you should set up the ant design ant design library goal to build a user login feature using google sign in on parse for a react app 1 installing dependencies the most popular way to enable google sign in on react is using react google login react google login to handle it set it up following the official docs make sure to create an oauth clientid clientid in your google credentials page, adding your local development address to the authorized urls, which generally is http //localhost 3000 http //localhost 3000 2 usign google sign in with parse let’s now create a new method inside the userlogin userlogin component that will handle the response when calling a google sign in authentication modal if the user signs in with google, this call will retrieve the user data from google and you need to store the id, idtoken idtoken , and google email then, the function will try to log in on parse using the parse user linkwith parse user linkwith method and these credentials note that if your user had already signed up using this google authentication, linkwith linkwith will log him in using the existent account javascript 1 const handlegoogleloginloginresponse = async function(response) { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid = response googleid; 10 const usertokenid = response tokenid; 11 const useremail = response profileobj email; 12 // try to login on parse using linkwith and these credentials 13 // create a new parse user object 14 const usertologin = new parse user(); 15 // set username and email to match google email 16 usertologin set('username', useremail); 17 usertologin set('email', useremail); 18 try { 19 let loggedinuser = await usertologin 20 linkwith('google', { 21 authdata {id usergoogleid, id token usertokenid}, 22 }); 23 // login returns the corresponding parseuser object 24 alert( 25 `success! user ${loggedinuser get('username')} has successfully signed in!`, 26 ); 27 // update state variable holding current user 28 getcurrentuser(); 29 return true; 30 } catch (error) { 31 // error can be caused by wrong parameters or lack of internet connection 32 alert(`error! ${error message}`); 33 return false; 34 } 35 } catch (error) { 36 console log("error gathering google user info, please try again!") 37 return false; 38 } 39 } 40 }1 const handlegoogleloginloginresponse = async function(response any) promise\<boolean> { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid string = response googleid; 10 const usertokenid string = response tokenid; 11 const useremail string = response profileobj email; 12 // try to login on parse using linkwith and these credentials 13 // create a new parse user object 14 const usertologin parse user = new parse user(); 15 // set username and email to match google email 16 usertologin set('username', useremail); 17 usertologin set('email', useremail); 18 try { 19 let loggedinuser parse user = await usertologin 20 linkwith('google', { 21 authdata {id usergoogleid, id token usertokenid}, 22 }); 23 // login returns the corresponding parseuser object 24 alert( 25 `success! user ${loggedinuser get('username')} has successfully signed in!`, 26 ); 27 // update state variable holding current user 28 getcurrentuser(); 29 return true; 30 } catch (error any) { 31 // error can be caused by wrong parameters or lack of internet connection 32 alert(`error! ${error message}`); 33 return false; 34 } 35 } catch (error any) { 36 console log("error gathering google user info, please try again!") 37 return false; 38 } 39 } 40 } after that, you need to use the react google login react google login googlelogin googlelogin component to call the google signin modal, adding it to your jsx code you can use google’s default styling or create a custom one, which is the way followed by this guide here is the full userlogin userlogin component code, note the react google login react google login button and how it is tied to the modal response method created before javascript 1 import react, { usestate } from 'react'; 2 import parse from 'parse/dist/parse min js'; 3 import googlelogin from 'react google login'; 4 import ' /app css'; 5 import { button, divider, input } from 'antd'; 6	 7 export const userlogin = () => { 8 // state variables 9 const \[username, setusername] = usestate(''); 10 const \[password, setpassword] = usestate(''); 11 const \[currentuser, setcurrentuser] = usestate(null); 12	 13 const douserlogin = async function () { 14 // note that these values come from state variables that we've declared before 15 const usernamevalue = username; 16 const passwordvalue = password; 17 try { 18 const loggedinuser = await parse user login(usernamevalue, passwordvalue); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get( 22 'username' 23 )} has successfully signed in!` 24 ); 25 // to verify that this is in fact the current user, `current` can be used 26 const currentuser = await parse user current(); 27 console log(loggedinuser === currentuser); 28 // clear input fields 29 setusername(''); 30 setpassword(''); 31 // update state variable holding current user 32 getcurrentuser(); 33 return true; 34 } catch (error) { 35 // error can be caused by wrong parameters or lack of internet connection 36 alert(`error! ${error message}`); 37 return false; 38 } 39 }; 40	 41 const douserlogout = async function () { 42 try { 43 await parse user logout(); 44 // to verify that current user is now empty, currentasync can be used 45 const currentuser = await parse user current(); 46 if (currentuser === null) { 47 alert('success! no user is logged in anymore!'); 48 } 49 // update state variable holding current user 50 getcurrentuser(); 51 return true; 52 } catch (error) { 53 alert(`error! ${error message}`); 54 return false; 55 } 56 }; 57	 58 // function that will return current user and also update current username 59 const getcurrentuser = async function () { 60 const currentuser = await parse user current(); 61 // update state variable holding current user 62 setcurrentuser(currentuser); 63 return currentuser; 64 }; 65	 66 const handlegoogleloginloginresponse = async function (response) { 67 // check if response has an error 68 if (response error !== undefined) { 69 console log(`error ${response error}`); 70 return false; 71 } else { 72 try { 73 // gather google user info 74 const usergoogleid = response googleid; 75 const usertokenid = response tokenid; 76 const useremail = response profileobj email; 77 // try to login on parse using linkwith and these credentials 78 // create a new parse user object 79 const usertologin = new parse user(); 80 // set username and email to match google email 81 usertologin set('username', useremail); 82 usertologin set('email', useremail); 83 try { 84 let loggedinuser = await usertologin linkwith('google', { 85 authdata { id usergoogleid, id token usertokenid }, 86 }); 87 // login returns the corresponding parseuser object 88 alert( 89 `success! user ${loggedinuser get( 90 'username' 91 )} has successfully signed in!` 92 ); 93 // update state variable holding current user 94 getcurrentuser(); 95 return true; 96 } catch (error) { 97 // error can be caused by wrong parameters or lack of internet connection 98 alert(`error! ${error message}`); 99 return false; 100 } 101 } catch (error) { 102 console log('error gathering google user info, please try again!'); 103 return false; 104 } 105 } 106 }; 107	 108 return ( 109 \<div> 110 \<div classname="header"> 111 \<img 112 classname="header logo" 113 alt="back4app logo" 114 src={ 115 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png' 116 } 117 /> 118 \<p classname="header text bold">{'react on back4app'}\</p> 119 \<p classname="header text">{'user login'}\</p> 120 \</div> 121 {currentuser === null && ( 122 \<div classname="container"> 123 \<h2 classname="heading">{'user login'}\</h2> 124 \<divider /> 125 \<div classname="form wrapper"> 126 \<input 127 value={username} 128 onchange={(event) => setusername(event target value)} 129 placeholder="username" 130 size="large" 131 classname="form input" 132 /> 133 \<input 134 value={password} 135 onchange={(event) => setpassword(event target value)} 136 placeholder="password" 137 size="large" 138 type="password" 139 classname="form input" 140 /> 141 \</div> 142 \<div classname="form buttons"> 143 \<button 144 onclick={() => douserlogin()} 145 type="primary" 146 classname="form button" 147 color={'#208aec'} 148 size="large" 149 block 150 > 151 log in 152 \</button> 153 \</div> 154 \<divider /> 155 \<div classname="login social"> 156 \<div classname="login social item login social item facebook"> 157 \<img classname="login social item image" src={'https //findicons com/files/icons/2830/clean social icons/250/facebook png'} alt=""/> 158 \</div> 159 \<googlelogin 160 clientid="108490793456 0flm4qh8ek4cb4krt7e06980o4sjvado apps googleusercontent com" 161 render={renderprops => ( 162 \<div classname="login social item"> 163 \<img onclick={renderprops onclick} classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaan8aaadicamaaad5w+jtaaabwvbmvex////qqzu0qfnchft7vauufppk7f08gvr0o/zzofb7uqd7uadpncp/vqdqpzaspk7plhrpoysyoklpoyzpnst97ovwgnskpensxfh8wgavouhplrj+9/b0pad4xsoix5fd7+h74udvenlru0f61tt1r6vuc2vtzvvxiop5zsvpnjb93p4nefofrpeqxpnk5dbus2zt9u++0vtuvyfelfwq1rt2u7j86ejyl5hrsz7/9+x80nt94637xdx8yu//+/d93jb+785sjvwdu/j+9nzc1fvv9p7a5v1frmdl8+nd4spru34zqklohwd0qktwhnpwdjf1ly/5ssl82ibuzjjyidl3pyfswdjwezb1mi7vazn8zwh+68l7wjdq04okszlurkrfuig7tjkgsersq1dsusqateq4o31kk9pjnrq/qmrijuvjmcrho5uyzqvkmmtioqjbqhlesjcm1x3qaaaltuleqvr4no2c2x/a2bwafrnibattyiiwmnusm46begyczdy7ctc47iztdkbjdj1u09ad9v9/qcqeskdlbrpx4pfvys9y+nzovefcbxpcb0hrlh+en9cnzg/lrn+fhieto+nuo9pmlqzkbezpyqhrrzz1zporwm4ddwuilauakhpfb5uiuzyicblsbfsodlm/kysgwv6izihta3l4kkip1670khljvqwjyvooqm2biak1j7f3lb81nbkkap6rnalzpo5vrpbp2okqq3nbowpyiz6kvqa23fkx1dmlwak2jgozovtrkpmt1k5rjguyqk5ugsi3z1h7wrxoza1xqglgflqk8zq975ip3rpn6dkda+r5esfr54vsymd4mjcjtrmmhs6tlc1pshfmpstqnta3vbmo2zloiuw5thch0lmzkqsu6+fhw46kigqhynlasxpmslubr8kd0ba77fboztvyi/oqhtoocx4ossqhlldldnympxyuei2rylhwrmnwi9orlkhpm9uipahqyzvzxojgjirhzx8wz80lspn8z30kxca3l4haj7dexym1k5vsmvg9ceoysm0vsao2yjkzrbfizjedjbxojkt1crgzojeq1cs3d1ypyt/tjddybb0dh3seo8d14qdhmnqn+bugktgb7hzzp45du0y0er2ytdseo3e+28njxcrovwdbvq8rt8pavq8st7mfrf6l9nwi5hrnewtbvh4mcbrs9r/ceuuh5aafmnpkktbjt+7ojnqtvr3e6h2d3xu7ykkgur8vgr65wacicjn/3pi8nijxzyyfsntohpxoiaw+uzhfbtjvwhkr0iyf3b8grhdiyvapcqecujn+fhd8f4awhtfbxvkjgjkboiaotxtf/vwitrlhidtfuybwrhbu8l5rqjp6zcy+tjq7iefl9bbh2slp6hftrowus6h2jvx25gkv6ehxpazsfaqybwotgit9iothtdwkrmdt/exzz6xk9e4wrh+h4/9yfplc5pxk6bsuoxjn/z0lf40e10vuziq2wbsbzfoooai99m6f6hevzx71r6dh5rfrgygsvx3wi0dvhle2rheehgw/rasf8ryjil5kvvwira/l+subezl58hw8odxh/d6afjzjpz58fqgrv2h93qb8y/gz/byqhimjhsct9fjqozqyscdxr2w/mbxv2qzfgpxpumt+brzcscn6pcf5fedwe/jrieetgwxd4mum5rt8fkbpjtfx2ejx6rmcb78jc6gqmmpg8oogtufyjuy6rn8zhk839qzb7wmfkzt4ubdb4qvlutke364e5fxgw8/goz/bzgwnv3og56iqpoy0wmsfwa8vvay1jm2d/ulp4beofb+wfmm43gxoetxcmpvvcpejkhwedbdyyp3cchzhvr1cubefmulvh0tm58hxs200m0kln2tp5cf47tphhysnpv/q4gk5kbqvwl8wjohdz5wjja7bqpixwpymhluezeb/9aksd4b+i4y7l5wtjrtao8vwu48stwo38vwb+qp+n7dwjopew/ilut/gpe0hjdzpdk/utg7e4/k9p0nt4ott6okvofwyehrc4/09gqrpv08e6f4cfjomv/2nywd+bqwx+tgzfnuxkz+o6exgdul89q/tbwj2z8v4yepr80svj5j3unplj4nxe2y/elt7xiqps/przm8r+4fq5sgdwf0o+j2yhxi4t7qj9vrcz285gfpt7xr74epr89tl2w+e0uulkun3co3ghz19uoyf3wldll/muwt5lqogvpucxx4o+r1b8ps8qx6lag+1esfurin67z/uun+igxkn5ffqg98hvw9+bp12fx7zdb+dre/lbe7o9mench5j6q9tp7rbs9t7z51d39rrb7jt+qpss1va6z/w01vllzh7s6v1o9z+ihydq8/p3n+bov5lzv7u3on9wmc7g1skzn9+b99+4i6er6z2d3f1fozx0g9glznnm+sd3b+gbbnypr3cxuigc2bs7hes2hfa90oon99c3u/j/i4hfsvzd7gvfpb3pkzfeh8zkmh1iyhsun/g1t6w39xjr8ha2k3kawdxwpn9i8/zuhxld4c0hn/v+moge4yrmyyqk703eh6r6xmcaiewzf7z0up1mso/k4gbuj4+ae+xw7m5ymri7xjcb3x6bggwhm/+aawho8og8hbm+d13fjj0ak5y00iampe7rzxewgdg9ocfesdsavgczvg9c300oh7o3gqxwgui8k02x2ycwuxs9q/8juqmvh9mejq7f5oapyps6sctpqp6fjcz53rxt8c/qmt/4mxhoabcfpfn4effotkti4fgklif1lrj5hrj096xqm122gdptlfv7qlmel5uftxzk8nrsmxdeyp5bbm+d/wz8ehq39xkkkfvoszpz/nps/x/ndwti1eg0iycmlv9vbxrzgmabuamnah05tbnuohbra4w7mowrzbfu5bamwzj55me7nswobljeqg+hdyt8vwl60xszjvti0rnjqhv2n3s09gj+bqsnoi05phryoh5pie3ngg82umadb1f7wc3dzq+wbwb9f/5alowb8hid9oewmwn85t/bswmgyi3bdsibegwrxvojetnxmzcwhyggs9g+k6t1fdytnkbmzs2uy5byklzz392mrljkh68htlaal7pd3yxuvgr/iw6ge2hh05oj5wtiypaahljiqjvu4kpnk/vsmryrppj+sl5zvsrgp5vcbcp6qic6pxsjj68rdkityf81igyhy/pjff0p2kkvzdwcdwyxzbxr6rcep0yzejthyw+iym6nxfcmqnw9jek5aqih8f1ewveap3ht9laqnx5vymfeotxixb5jeqghmv3my+al3d7d3jb4nq3bgokszduaxox7i9u+897+789ybx1n/n5m8bk0iuh2jgct9v18ug//rno8csg83qxx8tq01bxqzviosn0uuvb0u2/yhluz1vcgyfuak23u6dv8dydvxl1+696+2+ioz3+677tp5eqnbxv0ewm9gn98byoe6fm7x+bcwvibviboyc6fhv1ohr3fsshtxf1ikk+ctbnjcbcatq52bdssx11vr2mqupzrn+v1wr9fn82vq/op2rruav7s97+dnspbrxih9fhxkj4suqgpufpyfwulrysbglmollt5j7mecsbfn7mqgancx6riez4odghnztx8perdcsuj2/cdbza3yyjhmbmjr19xasc8tkgb0n/j1+oigy+bdinkffuf/bjuztbt6aal0hvzga4rfzghllwiotnoqbb9pkxj5wguerdcchi3ljiekmqwzvnjhvvmwzefpkxjzegusgcoer8fscocdqbgetk4cjmkbpuzravmsekxmus4w9/so7ksenfbhy1fltgm7n/ivzxt4hxhestvs+x6jneq5phze1rknrgejdozxyur+kzgf0g6krxz+mmpgveca6ltebxgisshtw9zhecbqee0wunkxr7hfwjvde3ypujuusxopnoo/o0/dgdlyg7aazi56vnyzyh1hla99mhi4/duoiror5o6qi/pdxx69mart3otfkkhjqd76qpq0vkssovq7s/jwdxq2uysusufuftg0udq6k4qrgymzfigoe4ngixfuepm7zxi6qhulplbmcxhpafijlk37p2wlorsiqvjv2dm/ikfsbb96uq0yvtmbmpm4jzhhsomhec7musrfyzjxt0mep6ctcox5qsqo1+gobobi6vzmkzltsma+prfot2lwvmqbwnvycbepfi2b9xb7x5g0vy9lsubbndwaa6zvmpgygwrm3g1dfgkqnforrc+jm3rtzvepkriayhnzc1i5sdsmlk/whcjdwqyatpyaaaaabjru5erkjggg=='} alt=""/> 164 \</div> 165 )} 166 buttontext="login" 167 onsuccess={handlegoogleloginloginresponse} 168 onfailure={handlegoogleloginloginresponse} 169 cookiepolicy={'single host origin'} 170 /> 171 \<div classname="login social item"> 172 \<img classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaaoeaaadhcamaaaajbsjiaaaav1bmvewzmzn///+skpkvlzwrkzh19fwgokdg4ocampqjo6p8/py+vr7l5ex29vb5+fniymirq6vq0ndp6enw1ta3t7fu1ns7u7uwsldkysrv7+/b29vi4uktra2ojcyuaaajguleqvr4no2d6zrqiaygkdsldrsrvh3v/zppq6pjjculxhlnod9/av8lauistkjsq8oxaetzfgjkclqhrboojxxoglcvae0dyz33doyitxdoubnhnrvhdysfqjoacfd7c4f39whxhfvj99cig/obryesbbpwqjjl7apfn7kl1rifmfavziebchzq2fqgdqwe9cgi/ckcctqfn/cyevh6sbqfnxapajysd4hnwacalpd4qmtc3gnjlsnqwprgjiwgqjnkgjq4hbxqrxvnrr4sk/atbpqzhjejd2ax7yfhh8hjihloyudjzb4tjzd3rwrko2k8wgu8chtlkreoteirrha+yzkhj8uibje+amwj9krihb9yh5vzdq+krijzurkhxllxclfivnhrjfwsoityijqbhzeik5rqzkl6vhrctiukogiud5nriix0flpw8gkxcffdkmdmkiieh9gntd8lhxebcdfrkvtleqixliq1il0+try5gj6rturwss+bnhdzf0pofgdnt7geavmrd+k9jiecwq5esqx3tzmthihcfwbot1gaw/avgnmtdocrer+dgyynzpye0lb0oskjfz3uzzvxphbqwpxhqzpkltxundxhbjtqgdhf9g9pihsv+4cjbkkxtilnhd5ntbj5rejs7vdaj05us9mfny+rxmrbvzu54rebc9acqhd/vssdj3jgd+3mvcq2agpjzwyg2nemr9d/qprwh89j0xwxn/xsactxwgyltpzp+53ymju1exu8pnxm04shbv4uba/befibumwzn6ewpk5kc27p29worbp5uw02sk8rbo6tsw+xy/1bwddv3j3cotpz612xu9s0x6bv+qthsxpenxqm8mvox2weijnq1rvf1wysx0mjz4vbzwd7v9prxmm2n6foadt1byu4zsywwtko/cevr2qkzaqds2jb1xz3pmyqwg2v7/jkabb1dqbdjnefr8acmyadccvwf355p24x0tcqkym986e9hsuktvjp2x/6on7u/aptc/l8381lzfpnjczxmbgp+nlt11x3gr3tdpt8n6xufboe4tp76rwgduv2qooonxpwwalrikx48fx7myftopvbpj7kiurceqdxsoljyrcgd8gxitiy6yrduov7nsyoscbsxeapqhbekqfsqaiikxcnsytehjkbgigc+rfz6dikkeny6loi93kgz5xcenanietgeahxcpsealmomggbuk0zvclbysc4yapzypwftxgoirz/okbudrtjumiyngeiu0mameiwweeb8o0fqrhsbmucvkveckeijg0i+pphqt1mxs0pfgyyem2/iiosiew4hvyirxpaitjiqpstep37ekhquwipb4oqowzdso/uhagvf0jgtgza2cj+hiycdibq8yo0zzzq+wkv7+xztfj8hirtdcv/0k+i59dfusoqmoelxopyrfthafqt7tv2uvjcjxcqtatcffof4uztj+xmfbchxu/fiqfojcsqx0qto3xir6h3rmac+gjxwjsppw3aq4gl60ytp4nwq6h3nuqc+gi1+i8c5ueme2o1ni6fhokh1lpzcqjzok6odtm9zan6cbdacxnbcoaqlwiuryelzmcjte7vawynh1drzbfsngocuovmma2oezjoqhu6taezfeoewinoaialcuk8mgukhzrxgyvckzu0corqj9x+e/4nvokvlbzfjdak0+69cmvmfl2eafno72vpxfbeagnfdk9q1zrio2c161itujx23p7gbveqymp/r/1hsonpcukgbfxcwtgdie4ilp6lqwbtm06o9nw0oatvokheoyf+dunjhhqd9vh3jowtoiw344ndtccjfqd4sxffnh2x2l7kp8j3ekqdepl7rn8pd2wov7gxpb9dpilh3pzgivr7rgry6xopodo98cdlqmrm817fpodei7/0ez5iy0bihuh7clwec1/e8qz7cdwbgl5oli9wrxfdnohxsytxt67wkxerxaudrijddxnbzj+ul/connbr4729hkrn/ehuwfeds4k+hfztwaj1eqouoih6cxxpigdzskf1e2ovgdhilfhocjg3vr00/zkbo/miqlh9g49iykebcbu73o6fxf8brtcodkfdcykybbgqdtbccywubrgqdcl4kfv6rymyg/mm3xsqlx1hgidh23ttqwk5xv/9jevtpgjcgw5himmnab+v50qdjtr7jjgitwo0tpgoa9obpcelsdyjdl/gnzynnh1cwl+prfhvv8riutxv9k/ynpxihfqz2b7klbwaeb6nrffmjqkr0/rdnwdz74u2kkhiykr38jui8eh3ttfu97l+mqy4oelootv535+qwfageygoponaqlduzu0weh1kfor6wr+mzqaqbrv/rda2mprjfjsaerzqriju/hftml6glg2mnfp5lcrakuaoura+g0okibl9is0pfuzgjfr8mih8qvjdqwq9bmi4kzvq7xyde3nyzq3scifapojlunfjiccn0lojk43ghhchycj/vrilcos6uqxchb5tsjoij4dfnqocljjaivr3trupvjhvh2ghq5+mpfu6ezumve2kxobehqgqfuoe7ih5lcj7sk165tzduzolqe4ryvd80tlvl6n5xwxcjtuz0pfdpj4knxqgiuee4hdczb9/ce5k+uugvf6kf6kl5rl4ljc6taepwldctdyjp2vvhqgijjtuynn56mgesr0pkblrfsbmpmlngy5bnikumnbdao54j6aayatniu1wrxncpj6ej3yvpxhhmltyp35nbwrkrmtp2tjnlfvnaybpeszjyxhhz+fdfnexfbb+qdrdobtcs3qecjocnhiddv0zmqfu7zmqjjyc49gthmnroe/n7dkhfeazkksjkce1ewc9s5iss3dacnbscm/7ovgix9kwaexyz3qameka4305z1tqcbnpfmb0vhbnggqik1u++nlolg1nel415tikc0va7dmrjaj7rpq7x33vpvnfvzfltu3sl8resowhhfqsgcjex1p/lu7yl1vtbeb9qd6fjo05b1k7z1nxoy5ijldvzfu2b09lvzqb1x5/alyvmmpfht+c/6dv/qmh/ovcu90claaaaabjru5erkjggg=='} alt=""/> 173 \</div> 174 \</div> 175 \<p classname="form hint">don't have an account? \<a classname="form link" href="#">sign up\</a>\</p> 176 \</div> 177 )} 178 {currentuser !== null && ( 179 \<div classname="container"> 180 \<h2 classname="heading">{'user screen'}\</h2> 181 \<divider /> 182 \<h2 classname="heading">{`hello ${currentuser get('username')}!`}\</h2> 183 \<div classname="form buttons"> 184 \<button 185 onclick={() => douserlogout()} 186 type="primary" 187 classname="form button" 188 color={'#208aec'} 189 size="large" 190 block 191 > 192 log out 193 \</button> 194 \</div> 195 \</div> 196 )} 197 \</div> 198 ); 199 };1 import react, { usestate, fc, reactelement } from 'react'; 2 import ' /app css'; 3 import { button, divider, input } from 'antd'; 4 import googlelogin from 'react google login'; 5 const parse = require('parse/dist/parse min js'); 6	 7 export const userlogin fc<{}> = () reactelement => { 8 // state variables 9 const \[username, setusername] = usestate(''); 10 const \[password, setpassword] = usestate(''); 11 const \[currentuser, setcurrentuser] = usestate\<parse object | null>(null); 12	 13 const douserlogin = async function () promise\<boolean> { 14 // note that these values come from state variables that we've declared before 15 const usernamevalue string = username; 16 const passwordvalue string = password; 17 try { 18 const loggedinuser parse user = await parse user login(usernamevalue, passwordvalue); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get('username')} has successfully signed in!`, 22 ); 23 // to verify that this is in fact the current user, `current` can be used 24 const currentuser parse user = await parse user current(); 25 console log(loggedinuser === currentuser); 26 // clear input fields 27 setusername(''); 28 setpassword(''); 29 // update state variable holding current user 30 getcurrentuser(); 31 return true; 32 } catch (error any) { 33 // error can be caused by wrong parameters or lack of internet connection 34 alert(`error! ${error message}`); 35 return false; 36 } 37 }; 38	 39 const douserlogout = async function () promise\<boolean> { 40 try { 41 await parse user logout(); 42 // to verify that current user is now empty, currentasync can be used 43 const currentuser parse user = await parse user current(); 44 if (currentuser === null) { 45 alert('success! no user is logged in anymore!'); 46 } 47 // update state variable holding current user 48 getcurrentuser(); 49 return true; 50 } catch (error any) { 51 alert(`error! ${error message}`); 52 return false; 53 } 54 }; 55	 56 // function that will return current user and also update current username 57 const getcurrentuser = async function () promise\<parse user | null> { 58 const currentuser (parse user | null) = await parse user current(); 59 // update state variable holding current user 60 setcurrentuser(currentuser); 61 return currentuser; 62 } 63	 64 const handlegoogleloginloginresponse = async function(response any) promise\<boolean> { 65 // check if response has an error 66 if (response error !== undefined) { 67 console log(`error ${response error}`); 68 return false; 69 } else { 70 try { 71 // gather google user info 72 const usergoogleid string = response googleid; 73 const usertokenid string = response tokenid; 74 const useremail string = response profileobj email; 75 // try to login on parse using linkwith and these credentials 76 // create a new parse user object 77 const usertologin parse user = new parse user(); 78 // set username and email to match google email 79 usertologin set('username', useremail); 80 usertologin set('email', useremail); 81 try { 82 let loggedinuser parse user = await usertologin 83 linkwith('google', { 84 authdata {id usergoogleid, id token usertokenid}, 85 }); 86 // login returns the corresponding parseuser object 87 alert( 88 `success! user ${loggedinuser get('username')} has successfully signed in!`, 89 ); 90 // update state variable holding current user 91 getcurrentuser(); 92 return true; 93 } catch (error any) { 94 // error can be caused by wrong parameters or lack of internet connection 95 alert(`error! ${error message}`); 96 return false; 97 } 98 } catch (error any) { 99 console log("error gathering google user info, please try again!") 100 return false; 101 } 102 } 103 } 104	 105 return ( 106 \<div> 107 \<div classname="header"> 108 \<img 109 classname="header logo" 110 alt="back4app logo" 111 src={ 112 'https //blog back4app com/wp content/uploads/2019/05/back4app white logo 500px png' 113 } 114 /> 115 \<p classname="header text bold">{'react on back4app'}\</p> 116 \<p classname="header text">{'user login'}\</p> 117 \</div> 118 {currentuser === null && ( 119 \<div classname="container"> 120 \<h2 classname="heading">{'user login'}\</h2> 121 \<divider /> 122 \<div classname="form wrapper"> 123 \<input 124 value={username} 125 onchange={(event) => setusername(event target value)} 126 placeholder="username" 127 size="large" 128 classname="form input" 129 /> 130 \<input 131 value={password} 132 onchange={(event) => setpassword(event target value)} 133 placeholder="password" 134 size="large" 135 type="password" 136 classname="form input" 137 /> 138 \</div> 139 \<div classname="form buttons"> 140 \<button 141 onclick={() => douserlogin()} 142 type="primary" 143 classname="form button" 144 color={'#208aec'} 145 size="large" 146 block 147 > 148 log in 149 \</button> 150 \</div> 151 \<divider /> 152 \<div classname="login social"> 153 \<div classname="login social item login social item facebook"> 154 \<img classname="login social item image" src={'https //findicons com/files/icons/2830/clean social icons/250/facebook png'} alt=""/> 155 \</div> 156 \<googlelogin 157 clientid="108490793456 0flm4qh8ek4cb4krt7e06980o4sjvado apps googleusercontent com" 158 render={renderprops => ( 159 \<div classname="login social item"> 160 \<img onclick={renderprops onclick} classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaan8aaadicamaaad5w+jtaaabwvbmvex////qqzu0qfnchft7vauufppk7f08gvr0o/zzofb7uqd7uadpncp/vqdqpzaspk7plhrpoysyoklpoyzpnst97ovwgnskpensxfh8wgavouhplrj+9/b0pad4xsoix5fd7+h74udvenlru0f61tt1r6vuc2vtzvvxiop5zsvpnjb93p4nefofrpeqxpnk5dbus2zt9u++0vtuvyfelfwq1rt2u7j86ejyl5hrsz7/9+x80nt94637xdx8yu//+/d93jb+785sjvwdu/j+9nzc1fvv9p7a5v1frmdl8+nd4spru34zqklohwd0qktwhnpwdjf1ly/5ssl82ibuzjjyidl3pyfswdjwezb1mi7vazn8zwh+68l7wjdq04okszlurkrfuig7tjkgsersq1dsusqateq4o31kk9pjnrq/qmrijuvjmcrho5uyzqvkmmtioqjbqhlesjcm1x3qaaaltuleqvr4no2c2x/a2bwafrnibattyiiwmnusm46begyczdy7ctc47iztdkbjdj1u09ad9v9/qcqeskdlbrpx4pfvys9y+nzovefcbxpcb0hrlh+en9cnzg/lrn+fhieto+nuo9pmlqzkbezpyqhrrzz1zporwm4ddwuilauakhpfb5uiuzyicblsbfsodlm/kysgwv6izihta3l4kkip1670khljvqwjyvooqm2biak1j7f3lb81nbkkap6rnalzpo5vrpbp2okqq3nbowpyiz6kvqa23fkx1dmlwak2jgozovtrkpmt1k5rjguyqk5ugsi3z1h7wrxoza1xqglgflqk8zq975ip3rpn6dkda+r5esfr54vsymd4mjcjtrmmhs6tlc1pshfmpstqnta3vbmo2zloiuw5thch0lmzkqsu6+fhw46kigqhynlasxpmslubr8kd0ba77fboztvyi/oqhtoocx4ossqhlldldnympxyuei2rylhwrmnwi9orlkhpm9uipahqyzvzxojgjirhzx8wz80lspn8z30kxca3l4haj7dexym1k5vsmvg9ceoysm0vsao2yjkzrbfizjedjbxojkt1crgzojeq1cs3d1ypyt/tjddybb0dh3seo8d14qdhmnqn+bugktgb7hzzp45du0y0er2ytdseo3e+28njxcrovwdbvq8rt8pavq8st7mfrf6l9nwi5hrnewtbvh4mcbrs9r/ceuuh5aafmnpkktbjt+7ojnqtvr3e6h2d3xu7ykkgur8vgr65wacicjn/3pi8nijxzyyfsntohpxoiaw+uzhfbtjvwhkr0iyf3b8grhdiyvapcqecujn+fhd8f4awhtfbxvkjgjkboiaotxtf/vwitrlhidtfuybwrhbu8l5rqjp6zcy+tjq7iefl9bbh2slp6hftrowus6h2jvx25gkv6ehxpazsfaqybwotgit9iothtdwkrmdt/exzz6xk9e4wrh+h4/9yfplc5pxk6bsuoxjn/z0lf40e10vuziq2wbsbzfoooai99m6f6hevzx71r6dh5rfrgygsvx3wi0dvhle2rheehgw/rasf8ryjil5kvvwira/l+subezl58hw8odxh/d6afjzjpz58fqgrv2h93qb8y/gz/byqhimjhsct9fjqozqyscdxr2w/mbxv2qzfgpxpumt+brzcscn6pcf5fedwe/jrieetgwxd4mum5rt8fkbpjtfx2ejx6rmcb78jc6gqmmpg8oogtufyjuy6rn8zhk839qzb7wmfkzt4ubdb4qvlutke364e5fxgw8/goz/bzgwnv3og56iqpoy0wmsfwa8vvay1jm2d/ulp4beofb+wfmm43gxoetxcmpvvcpejkhwedbdyyp3cchzhvr1cubefmulvh0tm58hxs200m0kln2tp5cf47tphhysnpv/q4gk5kbqvwl8wjohdz5wjja7bqpixwpymhluezeb/9aksd4b+i4y7l5wtjrtao8vwu48stwo38vwb+qp+n7dwjopew/ilut/gpe0hjdzpdk/utg7e4/k9p0nt4ott6okvofwyehrc4/09gqrpv08e6f4cfjomv/2nywd+bqwx+tgzfnuxkz+o6exgdul89q/tbwj2z8v4yepr80svj5j3unplj4nxe2y/elt7xiqps/przm8r+4fq5sgdwf0o+j2yhxi4t7qj9vrcz285gfpt7xr74epr89tl2w+e0uulkun3co3ghz19uoyf3wldll/muwt5lqogvpucxx4o+r1b8ps8qx6lag+1esfurin67z/uun+igxkn5ffqg98hvw9+bp12fx7zdb+dre/lbe7o9mench5j6q9tp7rbs9t7z51d39rrb7jt+qpss1va6z/w01vllzh7s6v1o9z+ihydq8/p3n+bov5lzv7u3on9wmc7g1skzn9+b99+4i6er6z2d3f1fozx0g9glznnm+sd3b+gbbnypr3cxuigc2bs7hes2hfa90oon99c3u/j/i4hfsvzd7gvfpb3pkzfeh8zkmh1iyhsun/g1t6w39xjr8ha2k3kawdxwpn9i8/zuhxld4c0hn/v+moge4yrmyyqk703eh6r6xmcaiewzf7z0up1mso/k4gbuj4+ae+xw7m5ymri7xjcb3x6bggwhm/+aawho8og8hbm+d13fjj0ak5y00iampe7rzxewgdg9ocfesdsavgczvg9c300oh7o3gqxwgui8k02x2ycwuxs9q/8juqmvh9mejq7f5oapyps6sctpqp6fjcz53rxt8c/qmt/4mxhoabcfpfn4effotkti4fgklif1lrj5hrj096xqm122gdptlfv7qlmel5uftxzk8nrsmxdeyp5bbm+d/wz8ehq39xkkkfvoszpz/nps/x/ndwti1eg0iycmlv9vbxrzgmabuamnah05tbnuohbra4w7mowrzbfu5bamwzj55me7nswobljeqg+hdyt8vwl60xszjvti0rnjqhv2n3s09gj+bqsnoi05phryoh5pie3ngg82umadb1f7wc3dzq+wbwb9f/5alowb8hid9oewmwn85t/bswmgyi3bdsibegwrxvojetnxmzcwhyggs9g+k6t1fdytnkbmzs2uy5byklzz392mrljkh68htlaal7pd3yxuvgr/iw6ge2hh05oj5wtiypaahljiqjvu4kpnk/vsmryrppj+sl5zvsrgp5vcbcp6qic6pxsjj68rdkityf81igyhy/pjff0p2kkvzdwcdwyxzbxr6rcep0yzejthyw+iym6nxfcmqnw9jek5aqih8f1ewveap3ht9laqnx5vymfeotxixb5jeqghmv3my+al3d7d3jb4nq3bgokszduaxox7i9u+897+789ybx1n/n5m8bk0iuh2jgct9v18ug//rno8csg83qxx8tq01bxqzviosn0uuvb0u2/yhluz1vcgyfuak23u6dv8dydvxl1+696+2+ioz3+677tp5eqnbxv0ewm9gn98byoe6fm7x+bcwvibviboyc6fhv1ohr3fsshtxf1ikk+ctbnjcbcatq52bdssx11vr2mqupzrn+v1wr9fn82vq/op2rruav7s97+dnspbrxih9fhxkj4suqgpufpyfwulrysbglmollt5j7mecsbfn7mqgancx6riez4odghnztx8perdcsuj2/cdbza3yyjhmbmjr19xasc8tkgb0n/j1+oigy+bdinkffuf/bjuztbt6aal0hvzga4rfzghllwiotnoqbb9pkxj5wguerdcchi3ljiekmqwzvnjhvvmwzefpkxjzegusgcoer8fscocdqbgetk4cjmkbpuzravmsekxmus4w9/so7ksenfbhy1fltgm7n/ivzxt4hxhestvs+x6jneq5phze1rknrgejdozxyur+kzgf0g6krxz+mmpgveca6ltebxgisshtw9zhecbqee0wunkxr7hfwjvde3ypujuusxopnoo/o0/dgdlyg7aazi56vnyzyh1hla99mhi4/duoiror5o6qi/pdxx69mart3otfkkhjqd76qpq0vkssovq7s/jwdxq2uysusufuftg0udq6k4qrgymzfigoe4ngixfuepm7zxi6qhulplbmcxhpafijlk37p2wlorsiqvjv2dm/ikfsbb96uq0yvtmbmpm4jzhhsomhec7musrfyzjxt0mep6ctcox5qsqo1+gobobi6vzmkzltsma+prfot2lwvmqbwnvycbepfi2b9xb7x5g0vy9lsubbndwaa6zvmpgygwrm3g1dfgkqnforrc+jm3rtzvepkriayhnzc1i5sdsmlk/whcjdwqyatpyaaaaabjru5erkjggg=='} alt=""/> 161 \</div> 162 )} 163 buttontext="login" 164 onsuccess={handlegoogleloginloginresponse} 165 onfailure={handlegoogleloginloginresponse} 166 cookiepolicy={'single host origin'} 167 /> 168 \<div classname="login social item"> 169 \<img classname="login social item image" src={'data\ image/png;base64,ivborw0kggoaaaansuheugaaaoeaaadhcamaaaajbsjiaaaav1bmvewzmzn///+skpkvlzwrkzh19fwgokdg4ocampqjo6p8/py+vr7l5ex29vb5+fniymirq6vq0ndp6enw1ta3t7fu1ns7u7uwsldkysrv7+/b29vi4uktra2ojcyuaaajguleqvr4no2d6zrqiaygkdsldrsrvh3v/zppq6pjjculxhlnod9/av8lauistkjsq8oxaetzfgjkclqhrboojxxoglcvae0dyz33doyitxdoubnhnrvhdysfqjoacfd7c4f39whxhfvj99cig/obryesbbpwqjjl7apfn7kl1rifmfavziebchzq2fqgdqwe9cgi/ckcctqfn/cyevh6sbqfnxapajysd4hnwacalpd4qmtc3gnjlsnqwprgjiwgqjnkgjq4hbxqrxvnrr4sk/atbpqzhjejd2ax7yfhh8hjihloyudjzb4tjzd3rwrko2k8wgu8chtlkreoteirrha+yzkhj8uibje+amwj9krihb9yh5vzdq+krijzurkhxllxclfivnhrjfwsoityijqbhzeik5rqzkl6vhrctiukogiud5nriix0flpw8gkxcffdkmdmkiieh9gntd8lhxebcdfrkvtleqixliq1il0+try5gj6rturwss+bnhdzf0pofgdnt7geavmrd+k9jiecwq5esqx3tzmthihcfwbot1gaw/avgnmtdocrer+dgyynzpye0lb0oskjfz3uzzvxphbqwpxhqzpkltxundxhbjtqgdhf9g9pihsv+4cjbkkxtilnhd5ntbj5rejs7vdaj05us9mfny+rxmrbvzu54rebc9acqhd/vssdj3jgd+3mvcq2agpjzwyg2nemr9d/qprwh89j0xwxn/xsactxwgyltpzp+53ymju1exu8pnxm04shbv4uba/befibumwzn6ewpk5kc27p29worbp5uw02sk8rbo6tsw+xy/1bwddv3j3cotpz612xu9s0x6bv+qthsxpenxqm8mvox2weijnq1rvf1wysx0mjz4vbzwd7v9prxmm2n6foadt1byu4zsywwtko/cevr2qkzaqds2jb1xz3pmyqwg2v7/jkabb1dqbdjnefr8acmyadccvwf355p24x0tcqkym986e9hsuktvjp2x/6on7u/aptc/l8381lzfpnjczxmbgp+nlt11x3gr3tdpt8n6xufboe4tp76rwgduv2qooonxpwwalrikx48fx7myftopvbpj7kiurceqdxsoljyrcgd8gxitiy6yrduov7nsyoscbsxeapqhbekqfsqaiikxcnsytehjkbgigc+rfz6dikkeny6loi93kgz5xcenanietgeahxcpsealmomggbuk0zvclbysc4yapzypwftxgoirz/okbudrtjumiyngeiu0mameiwweeb8o0fqrhsbmucvkveckeijg0i+pphqt1mxs0pfgyyem2/iiosiew4hvyirxpaitjiqpstep37ekhquwipb4oqowzdso/uhagvf0jgtgza2cj+hiycdibq8yo0zzzq+wkv7+xztfj8hirtdcv/0k+i59dfusoqmoelxopyrfthafqt7tv2uvjcjxcqtatcffof4uztj+xmfbchxu/fiqfojcsqx0qto3xir6h3rmac+gjxwjsppw3aq4gl60ytp4nwq6h3nuqc+gi1+i8c5ueme2o1ni6fhokh1lpzcqjzok6odtm9zan6cbdacxnbcoaqlwiuryelzmcjte7vawynh1drzbfsngocuovmma2oezjoqhu6taezfeoewinoaialcuk8mgukhzrxgyvckzu0corqj9x+e/4nvokvlbzfjdak0+69cmvmfl2eafno72vpxfbeagnfdk9q1zrio2c161itujx23p7gbveqymp/r/1hsonpcukgbfxcwtgdie4ilp6lqwbtm06o9nw0oatvokheoyf+dunjhhqd9vh3jowtoiw344ndtccjfqd4sxffnh2x2l7kp8j3ekqdepl7rn8pd2wov7gxpb9dpilh3pzgivr7rgry6xopodo98cdlqmrm817fpodei7/0ez5iy0bihuh7clwec1/e8qz7cdwbgl5oli9wrxfdnohxsytxt67wkxerxaudrijddxnbzj+ul/connbr4729hkrn/ehuwfeds4k+hfztwaj1eqouoih6cxxpigdzskf1e2ovgdhilfhocjg3vr00/zkbo/miqlh9g49iykebcbu73o6fxf8brtcodkfdcykybbgqdtbccywubrgqdcl4kfv6rymyg/mm3xsqlx1hgidh23ttqwk5xv/9jevtpgjcgw5himmnab+v50qdjtr7jjgitwo0tpgoa9obpcelsdyjdl/gnzynnh1cwl+prfhvv8riutxv9k/ynpxihfqz2b7klbwaeb6nrffmjqkr0/rdnwdz74u2kkhiykr38jui8eh3ttfu97l+mqy4oelootv535+qwfageygoponaqlduzu0weh1kfor6wr+mzqaqbrv/rda2mprjfjsaerzqriju/hftml6glg2mnfp5lcrakuaoura+g0okibl9is0pfuzgjfr8mih8qvjdqwq9bmi4kzvq7xyde3nyzq3scifapojlunfjiccn0lojk43ghhchycj/vrilcos6uqxchb5tsjoij4dfnqocljjaivr3trupvjhvh2ghq5+mpfu6ezumve2kxobehqgqfuoe7ih5lcj7sk165tzduzolqe4ryvd80tlvl6n5xwxcjtuz0pfdpj4knxqgiuee4hdczb9/ce5k+uugvf6kf6kl5rl4ljc6taepwldctdyjp2vvhqgijjtuynn56mgesr0pkblrfsbmpmlngy5bnikumnbdao54j6aayatniu1wrxncpj6ej3yvpxhhmltyp35nbwrkrmtp2tjnlfvnaybpeszjyxhhz+fdfnexfbb+qdrdobtcs3qecjocnhiddv0zmqfu7zmqjjyc49gthmnroe/n7dkhfeazkksjkce1ewc9s5iss3dacnbscm/7ovgix9kwaexyz3qameka4305z1tqcbnpfmb0vhbnggqik1u++nlolg1nel415tikc0va7dmrjaj7rpq7x33vpvnfvzfltu3sl8resowhhfqsgcjex1p/lu7yl1vtbeb9qd6fjo05b1k7z1nxoy5ijldvzfu2b09lvzqb1x5/alyvmmpfht+c/6dv/qmh/ovcu90claaaaabjru5erkjggg=='} alt=""/> 170 \</div> 171 \</div> 172 \<p classname="form hint">don't have an account? \<a classname="form link" href="#">sign up\</a>\</p> 173 \</div> 174 )} 175 {currentuser !== null && ( 176 \<div classname="container"> 177 \<h2 classname="heading">{'user screen'}\</h2> 178 \<divider /> 179 \<h2 classname="heading">{`hello ${currentuser get('username')}!`}\</h2> 180 \<div classname="form buttons"> 181 \<button 182 onclick={() => douserlogout()} 183 type="primary" 184 classname="form button" 185 color={'#208aec'} 186 size="large" 187 block 188 > 189 log out 190 \</button> 191 \</div> 192 \</div> 193 )} 194 \</div> 195 ); 196 }; add these classes to your app css app css file if you want to fully render this component’s layout app css 1 @import ' antd/dist/antd css'; 2	 3 app { 4 text align center; 5 } 6	 7 html { 8 box sizing border box; 9 outline none; 10 overflow auto; 11 } 12	 13 , 14 before, 15 after { 16 margin 0; 17 padding 0; 18 box sizing inherit; 19 } 20	 21 h1, 22 h2, 23 h3, 24 h4, 25 h5, 26 h6 { 27 margin 0; 28 font weight bold; 29 } 30	 31 p { 32 margin 0; 33 } 34	 35 body { 36 margin 0; 37 background color #fff; 38 } 39	 40 container { 41 width 100%; 42 max width 900px; 43 margin auto; 44 padding 20px 0; 45 text align left; 46 } 47	 48 header { 49 align items center; 50 padding 25px 0; 51 background color #208aec; 52 } 53	 54 header logo { 55 height 55px; 56 margin bottom 20px; 57 object fit contain; 58 } 59	 60 header text bold { 61 margin bottom 3px; 62 color rgba(255, 255, 255, 0 9); 63 font size 16px; 64 font weight bold; 65 } 66	 67 header text { 68 color rgba(255, 255, 255, 0 9); 69 font size 15px; 70 } 71	 72 heading { 73 font size 22px; 74 } 75	 76 flex { 77 display flex; 78 } 79	 80 flex between { 81 display flex; 82 justify content space between; 83 } 84	 85 flex child { 86 flex 0 0 45%; 87 } 88	 89 heading button { 90 margin left 12px; 91 } 92	 93 list item { 94 padding bottom 15px; 95 margin bottom 15px; 96 border bottom 1px solid rgba(0, 0, 0, 0 06); 97 text align left; 98 } 99	 100 list item title { 101 color rgba(0, 0, 0, 0 87); 102 font size 17px; 103 } 104	 105 list item description { 106 color rgba(0, 0, 0, 0 5); 107 font size 15px; 108 } 109	 110 form input { 111 margin bottom 20px; 112 } 113	 114 login social { 115 display flex; 116 justify content center; 117 margin bottom 30px; 118 } 119	 120 login social item { 121 width 54px; 122 height 54px; 123 border radius 54px; 124 padding 12px; 125 margin 0 12px; 126 border 1px solid #e6e6e6; 127 box shadow 0 2px 4px #d6d6d6; 128 } 129	 130 login social item facebook { 131 padding 4px; 132 background color #3c5b9b; 133 } 134	 135 login social item image { 136 width 100%; 137 } 138	 139 form hint { 140 color rgba(0, 0, 0, 0 5); 141 font size 16px; 142 text align center; 143 } go ahead and test your new function if you were able to sign in to google and the parse linkwith linkwith call was successful, you should see a success message like this 3 verifying user sign in and session creation to make sure that the google sign in worked, you can look at your parse dashboard and see your new user user (if your google authentication data didn’t belong to another user), containing the google authdata authdata parameters you can also verify that a valid session was created in the dashboard, containing a pointer to that user user object 4 linking an existing user to google sign in another linkwith linkwith possible use is to link an existing user with another auth provider, in this case, google add this function that calls linkwith linkwith the same way as logging in to your userlogin userlogin component the only difference here is that instead of calling the method from an empty parse user parse user , you will use it from the currently logged in user object javascript 1 const handlegoogleloginlinkresponse = async function(response) { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid = response googleid; 10 const usertokenid = response tokenid; 11 // try to link current parse user using linkwith and these credentials 12 // get current user 13 const usertolink = await parse user current(); 14 try { 15 let loggedinuser = await usertolink 16 linkwith('google', { 17 authdata {id usergoogleid, id token usertokenid}, 18 }); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get( 22 'username', 23 )} has successfully linked his google account!`, 24 ); 25 // update state variable holding current user 26 getcurrentuser(); 27 return true; 28 } catch (error) { 29 // error can be caused by wrong parameters or lack of internet connection 30 alert(`error! ${error message}`); 31 return false; 32 } 33 } catch (error) { 34 console log("error gathering google user info, please try again!") 35 return false; 36 } 37 } 38 }1 const handlegoogleloginlinkresponse = async function(response any) promise\<boolean> { 2 // check if response has an error 3 if (response error !== undefined) { 4 console log(`error ${response error}`); 5 return false; 6 } else { 7 try { 8 // gather google user info 9 const usergoogleid string = response googleid; 10 const usertokenid string = response tokenid; 11 // try to link current parse user using linkwith and these credentials 12 // get current user 13 const usertolink parse user = await parse user current(); 14 try { 15 let loggedinuser parse user = await usertolink 16 linkwith('google', { 17 authdata {id usergoogleid, id token usertokenid}, 18 }); 19 // login returns the corresponding parseuser object 20 alert( 21 `success! user ${loggedinuser get( 22 'username', 23 )} has successfully linked his google account!`, 24 ); 25 // update state variable holding current user 26 getcurrentuser(); 27 return true; 28 } catch (error any) { 29 // error can be caused by wrong parameters or lack of internet connection 30 alert(`error! ${error message}`); 31 return false; 32 } 33 } catch (error any) { 34 console log("error gathering google user info, please try again!") 35 return false; 36 } 37 } 38 } assign this function to another react google login react google login component in your home screen, which is shown only when there is a current user logged in in your app test your new function, noting that the parse user parse user object authdata authdata value will be updated with the new auth provider data verify if the user has indeed updated in your parse server dashboard conclusion at the end of this guide, you learned how to log in, sign up or link existing parse users on react using google sign in with react google login react google login in the next guide, we will show you how to use apple sign in